From 66550f1e2539d801779d0d98c1a72e4c4b228794 Mon Sep 17 00:00:00 2001 From: ec- Date: Sat, 25 Jan 2025 15:28:34 +0200 Subject: [PATCH] Vulkan: revert "batch image uploads whenever possible", add more debug info, code cleanup --- code/renderervk/vk.c | 220 ++++++++++++++++++++++--------------------- code/renderervk/vk.h | 9 +- 2 files changed, 119 insertions(+), 110 deletions(-) diff --git a/code/renderervk/vk.c b/code/renderervk/vk.c index 9a7f2b419..4afa04a38 100644 --- a/code/renderervk/vk.c +++ b/code/renderervk/vk.c @@ -133,7 +133,7 @@ static PFN_vkDebugMarkerSetObjectNameEXT qvkDebugMarkerSetObjectNameEXT; //////////////////////////////////////////////////////////////////////////// // forward declaration -VkPipeline create_pipeline( const Vk_Pipeline_Def *def, renderPass_t renderPassIndex ); +VkPipeline create_pipeline( const Vk_Pipeline_Def *def, renderPass_t renderPassIndex, uint32_t def_index ); static uint32_t find_memory_type( uint32_t memory_type_bits, VkMemoryPropertyFlags properties ) { VkPhysicalDeviceMemoryProperties memory_properties; @@ -326,10 +326,11 @@ static VkCommandBuffer begin_command_buffer( void ) } -static void end_command_buffer( VkCommandBuffer command_buffer ) +static void end_command_buffer( VkCommandBuffer command_buffer, const char *location ) { VkSubmitInfo submit_info; VkCommandBuffer cmdbuf[1]; + VkResult res; cmdbuf[0] = command_buffer; @@ -345,20 +346,31 @@ static void end_command_buffer( VkCommandBuffer command_buffer ) submit_info.signalSemaphoreCount = 0; submit_info.pSignalSemaphores = NULL; - VK_CHECK( qvkQueueSubmit( vk.queue, 1, &submit_info, VK_NULL_HANDLE ) ); - VK_CHECK( qvkQueueWaitIdle( vk.queue ) ); + VK_CHECK( qvkQueueSubmit( vk.queue, 1, &submit_info, vk.aux_fence ) ); + + // 2 seconds should be more than enough to finish the job in normal conditions: + res = qvkWaitForFences( vk.device, 1, &vk.aux_fence, VK_TRUE, 2 * 1000000000ULL ); + if ( res != VK_SUCCESS ) { + ri.Error( ERR_FATAL, "vkWaitForFences() failed with %s at %s", vk_result_string( res ), location ); + } + + qvkResetFences( vk.device, 1, &vk.aux_fence ); qvkFreeCommandBuffers( vk.device, vk.command_pool, 1, cmdbuf ); } -static void record_image_layout_transition( VkCommandBuffer command_buffer, VkImage image, VkImageAspectFlags image_aspect_flags, VkImageLayout old_layout, VkImageLayout new_layout ) { +static void record_image_layout_transition( VkCommandBuffer command_buffer, VkImage image, VkImageAspectFlags image_aspect_flags, + VkImageLayout old_layout, VkImageLayout new_layout, uint32_t src_stage_override, uint32_t dst_stage_override ) { VkImageMemoryBarrier barrier; uint32_t src_stage, dst_stage; switch ( old_layout ) { case VK_IMAGE_LAYOUT_UNDEFINED: - src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + if ( src_stage_override != 0 ) + src_stage = src_stage_override; + else + src_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; barrier.srcAccessMask = VK_ACCESS_NONE; break; case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: @@ -608,10 +620,10 @@ static void vk_create_swapchain( VkPhysicalDevice physical_device, VkDevice devi for ( i = 0; i < vk.swapchain_image_count; i++ ) { record_image_layout_transition( command_buffer, vk.swapchain_images[i], VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, vk.initSwapchainLayout ); + VK_IMAGE_LAYOUT_UNDEFINED, vk.initSwapchainLayout, 0, 0 ); } - end_command_buffer( command_buffer ); + end_command_buffer( command_buffer, __func__ ); } } @@ -1041,20 +1053,20 @@ static void allocate_and_bind_image_memory(VkImage image) { VK_CHECK(qvkBindImageMemory(vk.device, image, chunk->memory, chunk->used - memory_requirements.size)); } -static VkCommandBuffer staging_command_buffer = VK_NULL_HANDLE; -void flush_staging_command_buffer( void ) +static void vk_clean_staging_buffer( void ) { - if ( staging_command_buffer != VK_NULL_HANDLE ) - { - end_command_buffer( staging_command_buffer ); - staging_command_buffer = VK_NULL_HANDLE; - } - //if ( vk_world.staging_buffer_offset != 0 ) // TODO: use it instead of command buffer check? - // { - // - // } - vk_world.staging_buffer_offset = 0; + if ( vk_world.staging_buffer != VK_NULL_HANDLE ) { + qvkDestroyBuffer( vk.device, vk_world.staging_buffer, NULL ); + vk_world.staging_buffer = VK_NULL_HANDLE; + } + + if ( vk_world.staging_buffer_memory != VK_NULL_HANDLE ) { + qvkFreeMemory( vk.device, vk_world.staging_buffer_memory, NULL ); + vk_world.staging_buffer_memory = VK_NULL_HANDLE; + } + + vk_world.staging_buffer_size = 0; } @@ -1066,21 +1078,12 @@ static void ensure_staging_buffer_allocation( VkDeviceSize size ) uint32_t memory_type; void *data; - if ( vk_world.staging_buffer_size - vk_world.staging_buffer_offset >= size ) - return; - - flush_staging_command_buffer(); - - if ( vk_world.staging_buffer_size - vk_world.staging_buffer_offset >= size ) + if ( vk_world.staging_buffer_size >= size ) return; - if (vk_world.staging_buffer != VK_NULL_HANDLE) - qvkDestroyBuffer(vk.device, vk_world.staging_buffer, NULL); - - if (vk_world.staging_buffer_memory != VK_NULL_HANDLE) - qvkFreeMemory(vk.device, vk_world.staging_buffer_memory, NULL); + vk_clean_staging_buffer(); - vk_world.staging_buffer_size = MAX( size, 1024 * 1024 ); + vk_world.staging_buffer_size = MAX( size, 2 * 1024 * 1024 ); buffer_desc.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; buffer_desc.pNext = NULL; @@ -1106,7 +1109,6 @@ static void ensure_staging_buffer_allocation( VkDeviceSize size ) VK_CHECK(qvkMapMemory(vk.device, vk_world.staging_buffer_memory, 0, VK_WHOLE_SIZE, 0, &data)); vk_world.staging_buffer_ptr = (byte*)data; - vk_world.staging_buffer_offset = 0; SET_OBJECT_NAME( vk_world.staging_buffer, "staging buffer", VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT ); SET_OBJECT_NAME( vk_world.staging_buffer_memory, "staging buffer memory", VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT ); @@ -1477,6 +1479,7 @@ static qboolean vk_create_device( VkPhysicalDevice physical_device, int device_i VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore; VkPhysicalDeviceVulkanMemoryModelFeatures memory_model; VkPhysicalDeviceBufferDeviceAddressFeatures devaddr_features; + VkPhysicalDevice8BitStorageFeatures storage_8bit_features; #endif ri.Printf( PRINT_ALL, "...selected physical device: %i\n", device_index ); @@ -1540,6 +1543,7 @@ static qboolean vk_create_device( VkPhysicalDevice physical_device, int device_i qboolean timelineSemaphore = qfalse; qboolean memoryModel = qfalse; qboolean devAddrFeat = qfalse; + qboolean storage8bit = qfalse; const void** pNextPtr; #endif uint32_t i, len, count = 0; @@ -1569,6 +1573,8 @@ static qboolean vk_create_device( VkPhysicalDevice physical_device, int device_i memoryModel = qtrue; } else if ( strcmp( ext, VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME ) == 0 ) { devAddrFeat = qtrue; + } else if ( strcmp( ext, VK_KHR_8BIT_STORAGE_EXTENSION_NAME ) == 0 ) { + storage8bit = qtrue; #endif } // add this device extension to glConfig @@ -1624,6 +1630,10 @@ static qboolean vk_create_device( VkPhysicalDevice physical_device, int device_i if ( devAddrFeat ) { device_extension_list[ device_extension_count++ ] = VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME; } + + if ( storage8bit ) { + device_extension_list[ device_extension_count++ ] = VK_KHR_8BIT_STORAGE_EXTENSION_NAME; + } #endif // _DEBUG qvkGetPhysicalDeviceFeatures( physical_device, &device_features ); @@ -1702,7 +1712,17 @@ static qboolean vk_create_device( VkPhysicalDevice physical_device, int device_i devaddr_features.bufferDeviceAddress = VK_TRUE; devaddr_features.bufferDeviceAddressCaptureReplay = VK_FALSE; devaddr_features.bufferDeviceAddressMultiDevice = VK_FALSE; - //pNextPtr = &devaddr_features.pNext; + pNextPtr = &devaddr_features.pNext; + } + + if ( storage8bit ) { + *pNextPtr = &storage_8bit_features; + storage_8bit_features.pNext = NULL; + storage_8bit_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES; + storage_8bit_features.storageBuffer8BitAccess = VK_TRUE; + storage_8bit_features.storagePushConstant8 = VK_FALSE; + storage_8bit_features.uniformAndStorageBuffer8BitAccess = VK_TRUE; + pNextPtr = &storage_8bit_features.pNext; } #endif res = qvkCreateDevice( physical_device, &device_desc, NULL, &vk.device ); @@ -2596,7 +2616,7 @@ qboolean vk_alloc_vbo( const byte *vbo_data, int vbo_size ) copyRegion[0].size = vbo_size; qvkCmdCopyBuffer( command_buffer, staging_vertex_buffer, vk.vbo.vertex_buffer, 1, ©Region[0] ); - end_command_buffer( command_buffer ); + end_command_buffer( command_buffer, __func__ ); qvkDestroyBuffer( vk.device, staging_vertex_buffer, NULL ); qvkFreeMemory( vk.device, staging_buffer_memory, NULL ); @@ -3206,10 +3226,10 @@ static void vk_alloc_attachments( void ) attachments[i].descriptor, attachments[i].aspect_flags, VK_IMAGE_LAYOUT_UNDEFINED, // old_layout - attachments[i].image_layout - ); + attachments[i].image_layout, + 0, 0 ); } - end_command_buffer( command_buffer ); + end_command_buffer( command_buffer, __func__ ); num_attachments = 0; } @@ -3596,6 +3616,13 @@ static void vk_create_sync_primitives( void ) { SET_OBJECT_NAME( vk.tess[i].rendering_finished, va( "rendering_finished semaphore %i", i ), VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT ); SET_OBJECT_NAME( vk.tess[i].rendering_finished_fence, va( "rendering_finished fence %i", i ), VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT ); } + + fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_desc.pNext = NULL; + fence_desc.flags = 0; + + VK_CHECK( qvkCreateFence( vk.device, &fence_desc, NULL, &vk.aux_fence ) ); + SET_OBJECT_NAME( vk.aux_fence, "aux fence", VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT ); } @@ -3608,6 +3635,8 @@ static void vk_destroy_sync_primitives( void ) { qvkDestroyFence( vk.device, vk.tess[i].rendering_finished_fence, NULL ); vk.tess[i].waitForFence = qfalse; } + + qvkDestroyFence( vk.device, vk.aux_fence, NULL ); } @@ -4408,11 +4437,7 @@ void vk_release_resources( void ) { for (i = 0; i < vk_world.num_image_chunks; i++) qvkFreeMemory(vk.device, vk_world.image_chunks[i].memory, NULL); - if (vk_world.staging_buffer != VK_NULL_HANDLE) - qvkDestroyBuffer(vk.device, vk_world.staging_buffer, NULL); - - if (vk_world.staging_buffer_memory != VK_NULL_HANDLE) - qvkFreeMemory(vk.device, vk_world.staging_buffer_memory, NULL); + vk_clean_staging_buffer(); for (i = 0; i < vk_world.num_samplers; i++) qvkDestroySampler(vk.device, vk_world.samplers[i], NULL); @@ -4456,7 +4481,7 @@ void vk_release_resources( void ) { } #if 0 -static void record_buffer_memory_barrier(VkCommandBuffer cb, VkBuffer buffer, VkDeviceSize size, +static void record_buffer_memory_barrier(VkCommandBuffer cb, VkBuffer buffer, VkDeviceSize size, VkDeviceSize offset, VkPipelineStageFlags src_stages, VkPipelineStageFlags dst_stages, VkAccessFlags src_access, VkAccessFlags dst_access) { @@ -4468,7 +4493,7 @@ static void record_buffer_memory_barrier(VkCommandBuffer cb, VkBuffer buffer, Vk barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrier.buffer = buffer; - barrier.offset = 0; + barrier.offset = offset; barrier.size = size; qvkCmdPipelineBarrier( cb, src_stages, dst_stages, 0, 0, NULL, 1, &barrier, 0, NULL ); @@ -4629,11 +4654,12 @@ static byte *resample_image_data( const int target_format, byte *data, const int void vk_upload_image_data( image_t *image, int x, int y, int width, int height, int mipmaps, byte *pixels, int size, qboolean update ) { - //VkCommandBuffer command_buffer; + VkCommandBuffer command_buffer; VkBufferImageCopy regions[16]; VkBufferImageCopy region; + byte *buf; - int bpp, i; + int bpp; int num_regions = 0; int buffer_size = 0; @@ -4676,31 +4702,25 @@ void vk_upload_image_data( image_t *image, int x, int y, int width, int height, ensure_staging_buffer_allocation( buffer_size ); - if ( staging_command_buffer == VK_NULL_HANDLE ) { - staging_command_buffer = begin_command_buffer(); - } - - for ( i = 0; i < num_regions; i++ ) { - regions[i].bufferOffset += vk_world.staging_buffer_offset; - } + Com_Memcpy( vk_world.staging_buffer_ptr, buf, buffer_size ); - Com_Memcpy( vk_world.staging_buffer_ptr + vk_world.staging_buffer_offset, buf, buffer_size ); - vk_world.staging_buffer_offset += buffer_size; + command_buffer = begin_command_buffer(); - //staging_command_buffer = begin_command_buffer(); - //record_buffer_memory_barrier( staging_command_buffer, vk_world.staging_buffer, VK_WHOLE_SIZE, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT ); + // record_buffer_memory_barrier( command_buffer, vk_world.staging_buffer, VK_WHOLE_SIZE, 0, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT ); if ( update ) { - record_image_layout_transition( staging_command_buffer, image->handle, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ); + record_image_layout_transition( command_buffer, image->handle, VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0 ); } else { - record_image_layout_transition( staging_command_buffer, image->handle, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ); + record_image_layout_transition( command_buffer, image->handle, VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_HOST_BIT, 0 ); } - qvkCmdCopyBufferToImage( staging_command_buffer, vk_world.staging_buffer, image->handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, num_regions, regions ); + qvkCmdCopyBufferToImage( command_buffer, vk_world.staging_buffer, image->handle, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, num_regions, regions ); - record_image_layout_transition( staging_command_buffer, image->handle, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ); + record_image_layout_transition( command_buffer, image->handle, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, 0 ); - // flush_staging_command_buffer(); // uncomment for old single-image sync behavior + end_command_buffer( command_buffer, __func__ ); if ( buf != pixels ) { ri.Hunk_FreeTempMemory( buf ); @@ -5286,7 +5306,7 @@ static void push_attr( uint32_t location, uint32_t binding, VkFormat format ) } -VkPipeline create_pipeline( const Vk_Pipeline_Def *def, renderPass_t renderPassIndex ) { +VkPipeline create_pipeline( const Vk_Pipeline_Def *def, renderPass_t renderPassIndex, uint32_t def_index ) { VkShaderModule *vs_module = NULL; VkShaderModule *fs_module = NULL; //int32_t vert_spec_data[1]; // clippping @@ -6057,7 +6077,7 @@ VkPipeline create_pipeline( const Vk_Pipeline_Def *def, renderPass_t renderPassI multisample_state.pNext = NULL; multisample_state.flags = 0; - multisample_state.rasterizationSamples = (vk.renderPassIndex == RENDER_PASS_SCREENMAP) ? vk.screenMapSamples : vkSamples; + multisample_state.rasterizationSamples = (renderPassIndex == RENDER_PASS_SCREENMAP) ? vk.screenMapSamples : vkSamples; multisample_state.sampleShadingEnable = VK_FALSE; multisample_state.minSampleShading = 1.0f; @@ -6241,6 +6261,8 @@ VkPipeline create_pipeline( const Vk_Pipeline_Def *def, renderPass_t renderPassI VK_CHECK( qvkCreateGraphicsPipelines( vk.device, vk.pipelineCache, 1, &create_info, NULL, &pipeline ) ); + SET_OBJECT_NAME( pipeline, va( "pipeline def#%i, pass#%i", def_index, renderPassIndex ), VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT ); + vk.pipeline_create_count++; return pipeline; @@ -6267,9 +6289,11 @@ uint32_t vk_alloc_pipeline( const Vk_Pipeline_Def *def ) { VkPipeline vk_gen_pipeline( uint32_t index ) { if ( index < vk.pipelines_count ) { VK_Pipeline_t *pipeline = vk.pipelines + index; - if ( pipeline->handle[ vk.renderPassIndex ] == VK_NULL_HANDLE ) - pipeline->handle[ vk.renderPassIndex ] = create_pipeline( &pipeline->def, vk.renderPassIndex ); - return pipeline->handle[ vk.renderPassIndex ]; + const renderPass_t pass = vk.renderPassIndex; + if ( pipeline->handle[ pass ] == VK_NULL_HANDLE ) { + pipeline->handle[ pass ] = create_pipeline( &pipeline->def, pass, index ); + } + return pipeline->handle[ pass ]; } else { return VK_NULL_HANDLE; } @@ -6435,8 +6459,7 @@ static void get_mvp_transform( float *mvp ) void vk_clear_color( const vec4_t color ) { VkClearAttachment attachment; - VkClearRect clear_rect[2]; - uint32_t rect_count; + VkClearRect clear_rect; if ( !vk.active ) return; @@ -6448,29 +6471,11 @@ void vk_clear_color( const vec4_t color ) { attachment.clearValue.color.float32[3] = color[3]; attachment.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - get_scissor_rect( &clear_rect[0].rect ); - clear_rect[0].baseArrayLayer = 0; - clear_rect[0].layerCount = 1; - rect_count = 1; - -#ifdef _DEBUG - // Split viewport rectangle into two non-overlapping rectangles. - // It's a HACK to prevent Vulkan validation layer's performance warning: - // "vkCmdClearAttachments() issued on command buffer object XXX prior to any Draw Cmds. - // It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw." - // - // NOTE: we don't use LOAD_OP_CLEAR for color attachment when we begin renderpass - // since at that point we don't know whether we need collor buffer clear (usually we don't). - { - uint32_t h = clear_rect[0].rect.extent.height / 2; - clear_rect[0].rect.extent.height = h; - clear_rect[1] = clear_rect[0]; - clear_rect[1].rect.offset.y = h; - rect_count = 2; - } -#endif + get_scissor_rect( &clear_rect.rect ); + clear_rect.baseArrayLayer = 0; + clear_rect.layerCount = 1; - qvkCmdClearAttachments( vk.cmd->command_buffer, 1, &attachment, rect_count, clear_rect ); + qvkCmdClearAttachments( vk.cmd->command_buffer, 1, &attachment, 1, &clear_rect ); } @@ -7007,8 +7012,6 @@ void vk_begin_frame( void ) //VkFramebuffer frameBuffer; VkResult res; - flush_staging_command_buffer(); // finish any pending texture uploads - if ( vk.frame_count++ ) // might happen during stereo rendering return; @@ -7054,14 +7057,16 @@ void vk_begin_frame( void ) VK_CHECK( qvkBeginCommandBuffer( vk.cmd->command_buffer, &begin_info ) ); // Ensure visibility of geometry buffers writes. - //record_buffer_memory_barrier( vk.cmd->command_buffer, vk.cmd->vertex_buffer, vk.cmd->vertex_buffer_offset, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT ); + //record_buffer_memory_barrier( vk.cmd->command_buffer, vk.cmd->vertex_buffer, vk.geometry_buffer_size, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT ); #if 0 // add explicit layout transition dependency if ( vk.fboActive ) { - record_image_layout_transition( vk.cmd->command_buffer, vk.color_image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ); + record_image_layout_transition( vk.cmd->command_buffer, vk.color_image, VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 0, 0 ); } else { - record_image_layout_transition( vk.cmd->command_buffer, vk.swapchain_images[ vk.swapchain_image_index ], VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR ); + record_image_layout_transition( vk.cmd->command_buffer, vk.swapchain_images[ vk.swapchain_image_index ], VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 0, 0 ); } #endif @@ -7217,6 +7222,7 @@ void vk_end_frame( void ) // presentation may take undefined time to complete, we can't measure it in a reliable way backEnd.pc.msec = ri.Milliseconds() - backEnd.pc.msec; + vk.renderPassIndex = RENDER_PASS_MAIN; // vk_present_frame(); } @@ -7225,10 +7231,6 @@ void vk_present_frame( void ) VkPresentInfoKHR present_info; VkResult res; - // pickup next command buffer for rendering - vk.cmd_index++; - vk.cmd_index %= NUM_COMMAND_BUFFERS; - if ( ri.CL_IsMinimized() ) return; @@ -7261,6 +7263,11 @@ void vk_present_frame( void ) // or we don't ri.Error( ERR_FATAL, "vkQueuePresentKHR returned %s", vk_result_string( res ) ); } + + // pickup next command buffer for rendering + vk.cmd_index++; + vk.cmd_index %= NUM_COMMAND_BUFFERS; + vk.cmd = &vk.tess[ vk.cmd_index ]; } @@ -7377,13 +7384,14 @@ void vk_read_pixels( byte *buffer, uint32_t width, uint32_t height ) record_image_layout_transition( command_buffer, srcImage, VK_IMAGE_ASPECT_COLOR_BIT, srcImageLayout, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ); + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + 0, 0); } record_image_layout_transition( command_buffer, dstImage, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ); + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0 ); // end_command_buffer( command_buffer ); @@ -7427,7 +7435,7 @@ void vk_read_pixels( byte *buffer, uint32_t width, uint32_t height ) qvkCmdCopyImage( command_buffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion ); } - end_command_buffer( command_buffer ); + end_command_buffer( command_buffer, __func__ ); // Copy data from destination image to memory buffer. subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; @@ -7511,9 +7519,9 @@ void vk_read_pixels( byte *buffer, uint32_t width, uint32_t height ) record_image_layout_transition( command_buffer, srcImage, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - srcImageLayout ); + srcImageLayout, 0, 0 ); - end_command_buffer( command_buffer ); + end_command_buffer( command_buffer, "restore layout" ); } } diff --git a/code/renderervk/vk.h b/code/renderervk/vk.h index 5bd3f5b74..2fdc0b856 100644 --- a/code/renderervk/vk.h +++ b/code/renderervk/vk.h @@ -10,7 +10,7 @@ #define MIN_SWAPCHAIN_IMAGES_MAILBOX 3 #define MAX_VK_SAMPLERS 32 -#define MAX_VK_PIPELINES (1024 + 128) +#define MAX_VK_PIPELINES ((1024 + 128)*2) #define VERTEX_BUFFER_SIZE (4 * 1024 * 1024) #define IMAGE_CHUNK_SIZE (32 * 1024 * 1024) @@ -159,8 +159,8 @@ typedef struct { } Vk_Sampler_Def; typedef enum { - RENDER_PASS_SCREENMAP = 0, - RENDER_PASS_MAIN, + RENDER_PASS_MAIN = 0, + RENDER_PASS_SCREENMAP, RENDER_PASS_POST_BLOOM, RENDER_PASS_COUNT } renderPass_t; @@ -592,6 +592,8 @@ typedef struct { uint32_t maxBoundDescriptorSets; + VkFence aux_fence; + } Vk_Instance; typedef struct { @@ -619,7 +621,6 @@ typedef struct { VkBuffer staging_buffer; VkDeviceMemory staging_buffer_memory; VkDeviceSize staging_buffer_size; - VkDeviceSize staging_buffer_offset; byte *staging_buffer_ptr; // pointer to mapped staging buffer //