Render output flickers, probably due to uniform

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

It looks poorly formated. Use:

```
code1
code2
```

to make

code1
code2

How does the Rendering_update_uniform_buffer() look like?

PS: If it does vkUpdateDescriptorSets, then that means your command buffers become invalid.

Concerning formatting, the code-tags behave weirdly. I’ve got an opening code tag at the beginning of the code in my first post, and an ending tag at the end, but for some reason it leaves the last bit of code outside the scrollable “window”.

Anyways, here’s my Render_update_uniform_buffer:

void Rendering_update_uniform_buffer(uint32 p_image_index) {

    static float32 time = 0.0f;
    time += Time_delta();
    mat4 mvp = rotation(vec3{0.0f, 0.0f, 10.0f*time});
    auto &uniform_buffers = Memory_Global->Rendering_VK_uniform_buffers;
    Memory_host_to_device_copy(uniform_buffers + Memory_Global->Rendering_VK_current_frame, &mvp, sizeof(mvp));
}

void Memory_host_to_device_copy(DeviceMemory *p_dst, const void *p_src, uint64 p_size, uint64 p_dst_offset) {

    void *data;
    if (vkMapMemory(Memory_Global->Rendering_VK_logical_device, p_dst->memory, p_dst_offset, p_size, 0, &data) != VK_SUCCESS) {
        println("Error: vkMapMemory failed");
        exit(1);
    }
    Memory_host_copy(data, p_src, p_size);
    vkUnmapMemory(Memory_Global->Rendering_VK_logical_device, p_dst->memory);
}

Edit: I call vkUpdateDescriptorSets in _Rendering_create_descriptor_sets. Then, after all of these initialization functions have been called, I call Rendering_record_command_buffers, which looks like this:

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);
        }
    }
}

Cheers,
Miika Vihersaari

Most likely because your code tags are simply ignored and instead the indent block markup takes over. Just do what I say and it should be formated correctly.

Alright, the p_image_index parameter in Rendering_update_uniform_buffer() seem unused, which is suspicious. Instead it uses Rendering_VK_current_frame. That would not work though because the uniform you are updating would be bound to different command buffer than the one you use (which are indexed by image_index).

The results are magnificent! Both for code formatting here and for rendering after I fixed my mistake. Thank you again, @krOoze ! It indeed makes more sense to use the parameter of the update function for something rather than nothing :smiley:

About text formatting, is there a page on formatting instructions here somewhere where the three single quotes are explained, along with everything else you can do? I had no idea how to format code.

Cheers,
Miika Vihersaari

Good, good.

The formatting is just a standardish Markdown as used on lots of places like StackOverflow, Reddit, or GitHub. Code block is either indent everything by four spaces (which I personally find annoying), or surrounding it by the tripple tickmark. See e.g. the GitHubs flavor: Mastering Markdown · GitHub Guides. This here is Discourse engine I think, and other things might be allowed, IDK.

Exactly.

Here are some links on markup that generally seems to work well with Discourse:

This isn’t everything that’s supported, but it’s a good portion of it. A few random exceptions:

x2
x2
Blue text
Blue text
Yellow background color
Tab

Main Text ← (hover for Alt Text)

:khr:
:nvidia:
:amd:
:intel: