I’m going through vulkan-tutorial dot com and have so far gotten to uniforms. Everything up until this point has worked without a hitch. As soon as I pass in a uniform, every other frame (or third or so) of the render output comes out black (or whatever color I clear to). I’m pretty sure the problem is related to uniforms. I’ve double-checked my calls to vkWaitForFence for mistakes, but they’re exactly like in the tutorial. Here’s my render update:
void Rendering_update() {
auto &image_available_semaphores = Memory_Global->Rendering_VK_image_available_semaphores;
auto &render_finished_semaphores = Memory_Global->Rendering_VK_render_finished_semaphores;
auto &in_flight_fences = Memory_Global->Rendering_VK_in_flight_fences;
auto &in_flight_images = Memory_Global->Rendering_VK_in_flight_images;
vkWaitForFences(Memory_Global->Rendering_VK_logical_device, 1, in_flight_fences + Memory_Global->Rendering_VK_current_frame, VK_TRUE, Math_uint64_max);
uint32 image_index;
if (vkAcquireNextImageKHR(
Memory_Global->Rendering_VK_logical_device,
Memory_Global->Rendering_VK_swapchain,
Math_uint64_max,
image_available_semaphores[Memory_Global->Rendering_VK_current_frame],
VK_NULL_HANDLE,
&image_index
) != VK_SUCCESS) {
println("Error: vkAcquireNextImageKHR failed");
exit(1);
}
Rendering_update_uniform_buffer(image_index);
if (in_flight_images[image_index] != VK_NULL_HANDLE) {
if (vkWaitForFences(Memory_Global->Rendering_VK_logical_device, 1, in_flight_images + image_index, VK_TRUE, Math_uint64_max) != VK_SUCCESS) {
println("Error: vkWaitForFences failed");
exit(1);
}
}
in_flight_images[image_index] = in_flight_fences[Memory_Global->Rendering_VK_current_frame];
auto &command_buffers = Memory_Global->Rendering_VK_command_buffers;
VkSemaphore signal_semaphores[] = {render_finished_semaphores[Memory_Global->Rendering_VK_current_frame]};
VkSemaphore wait_semaphores[] = {image_available_semaphores[Memory_Global->Rendering_VK_current_frame]};
VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSubmitInfo submit_info = {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = wait_semaphores;
submit_info.pWaitDstStageMask = wait_stages;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = command_buffers + image_index;
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = signal_semaphores;
vkResetFences(Memory_Global->Rendering_VK_logical_device, 1, in_flight_fences + Memory_Global->Rendering_VK_current_frame);
if (vkQueueSubmit(Memory_Global->Rendering_VK_graphics_queue, 1, &submit_info, in_flight_fences[Memory_Global->Rendering_VK_current_frame]) != VK_SUCCESS) {
println("Error: vkQueueSubmit failed");
exit(1);
}
VkSwapchainKHR swapchains[] = {Memory_Global->Rendering_VK_swapchain};
VkPresentInfoKHR present_info = {};
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
present_info.waitSemaphoreCount = 1;
present_info.pWaitSemaphores = signal_semaphores;
present_info.swapchainCount = 1;
present_info.pSwapchains = swapchains;
present_info.pImageIndices = &image_index;
present_info.pResults = 0;
if (vkQueuePresentKHR(Memory_Global->Rendering_VK_present_queue, &present_info) != VK_SUCCESS) {
println("Error: vkQueuePresentKHR failed");
exit(1);
}
Memory_Global->Rendering_VK_current_frame = (Memory_Global->Rendering_VK_current_frame + 1) % Rendering_frames_in_flight_max;
}
// Just like the tutorial says, as soon as I get the index of the next image from vkAcquireNextImageKHR, I update my uniform buffer. And here's how I record my command buffers:
void Rendering_record_command_buffers() {
auto &framebuffers = Memory_Global->Rendering_VK_framebuffers;
auto &command_buffers = Memory_Global->Rendering_VK_command_buffers;
auto &descriptor_sets = Memory_Global->Rendering_VK_descriptor_sets;
for (uint32 i = 0; i < command_buffers.count; ++i) {
VkCommandBufferBeginInfo command_buffer_begin_info = {};
command_buffer_begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
command_buffer_begin_info.flags = 0;
command_buffer_begin_info.pInheritanceInfo = 0;
if (vkBeginCommandBuffer(command_buffers[i], &command_buffer_begin_info) != VK_SUCCESS) {
println("Error: vkBeginCommandBuffer failed");
exit(1);
} {
VkClearValue clear_color = {0.0f, 0.0f, 0.0f, 1.0f};
VkRenderPassBeginInfo render_pass_begin_info = {};
render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
render_pass_begin_info.renderPass = Memory_Global->Rendering_VK_render_pass;
render_pass_begin_info.framebuffer = framebuffers[i];
render_pass_begin_info.renderArea.offset = VkOffset2D{0, 0};
render_pass_begin_info.renderArea.extent = Memory_Global->Rendering_VK_swap_extent;
render_pass_begin_info.clearValueCount = 1;
render_pass_begin_info.pClearValues = &clear_color;
vkCmdBeginRenderPass(command_buffers[i], &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
{
VkBuffer vertex_buffers[Rendering_vertex_attributes_count] = {
Memory_Global->Rendering_VK_vertex_buffer.buffer,
Memory_Global->Rendering_VK_vertex_buffer.buffer,
};
VkDeviceSize offsets[Rendering_vertex_attributes_count] = {
0,
sizeof(Rendering_positions),
};
vkCmdBindVertexBuffers(command_buffers[i], 0, 2, vertex_buffers, offsets);
vkCmdBindIndexBuffer(command_buffers[i], Memory_Global->Rendering_VK_index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
vkCmdBindPipeline(command_buffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, Memory_Global->Rendering_VK_pipeline);
vkCmdBindDescriptorSets(
command_buffers[i],
VK_PIPELINE_BIND_POINT_GRAPHICS,
Memory_Global->Rendering_VK_pipeline_layout,
0,
1,
descriptor_sets + i,
0,
0
);
vkCmdDrawIndexed(command_buffers[i], sizeof(Rendering_indices)/sizeof(uint16), 1, 0, 0, 0);
}
vkCmdEndRenderPass(command_buffers[i]);
}
if (vkEndCommandBuffer(command_buffers[i]) != VK_SUCCESS) {
println("Error: vkEndCommandBuffer failed");
exit(1);
}
}
}
// And here's my initialization order:
...
_Rendering_create_window();
_Rendering_get_instance_layers_available();
_Rendering_get_instance_extensions_available();
_Rendering_create_instance();
_Rendering_create_debug_report_callback();
_Rendering_create_surface();
_Rendering_select_physical_device();
_Rendering_get_device_extensions_available();
_Rendering_create_logical_device();
_Rendering_get_device_queues();
_Rendering_get_surface_capabilities();
_Rendering_select_surface_format();
_Rendering_select_present_mode();
_Rendering_select_swap_extent();
_Rendering_create_swapchain();
_Rendering_get_swapchain_images();
_Rendering_create_image_views();
_Rendering_create_shader_modules();
_Rendering_create_render_pass();
_Rendering_create_descriptor_set_layout();
_Rendering_create_graphics_pipeline();
_Rendering_create_framebuffers();
_Rendering_create_uniform_buffers();
_Rendering_create_descriptor_pool();
_Rendering_create_descriptor_sets();
_Rendering_create_command_pools();
_Rendering_allocate_command_buffers();
_Rendering_create_semaphores();
_Rendering_create_vertex_buffer();
_Rendering_create_index_buffer();
Does that look right?
Cheers,
Miika Vihersaari