mirror of
				https://git.eden-emu.dev/eden-emu/eden.git
				synced 2025-10-25 09:38:24 +00:00 
			
		
		
		
	[vk] Bring Vulkan closer to Spec (#180)
The changes noted below bring Vulkan closer to 1.3 spec and get rid of validation errors and enable us to properly use one or two more functions. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/180 Reviewed-by: crueter <crueter@eden-emu.dev> Reviewed-by: Maufeat <sahyno1996@gmail.com> Co-authored-by: Shinmegumi <shinmegumi@eden-emu.dev> Co-committed-by: Shinmegumi <shinmegumi@eden-emu.dev>
This commit is contained in:
		
							parent
							
								
									383fb23348
								
							
						
					
					
						commit
						c8d6f23129
					
				
					 10 changed files with 176 additions and 122 deletions
				
			
		|  | @ -518,7 +518,7 @@ void BlitImageHelper::BlitColor(const Framebuffer* dst_framebuffer, VkImageView | |||
|     scheduler.RequestOutsideRenderPassOperationContext(); | ||||
|     scheduler.Record([this, dst_framebuffer, src_image_view, src_image, src_sampler, dst_region, | ||||
|                       src_region, src_size, pipeline, layout](vk::CommandBuffer cmdbuf) { | ||||
|         TransitionImageLayout(cmdbuf, src_image, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL); | ||||
|         TransitionImageLayout(cmdbuf, src_image,  VK_IMAGE_LAYOUT_GENERAL); | ||||
|         BeginRenderPass(cmdbuf, dst_framebuffer); | ||||
|         const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit(); | ||||
|         UpdateOneTextureDescriptorSet(device, descriptor_set, src_sampler, src_image_view); | ||||
|  |  | |||
|  | @ -502,7 +502,6 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) { | |||
| void GraphicsPipeline::ConfigureDraw(const RescalingPushConstant& rescaling, | ||||
|                                      const RenderAreaPushConstant& render_area) { | ||||
|     scheduler.RequestRenderpass(texture_cache.GetFramebuffer()); | ||||
| 
 | ||||
|     if (!is_built.load(std::memory_order::relaxed)) { | ||||
|         // Wait for the pipeline to be built
 | ||||
|         scheduler.Record([this](vk::CommandBuffer) { | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ | |||
| #include <unordered_map> | ||||
| #include <utility> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "video_core/renderer_vulkan/vk_texture_cache.h" | ||||
| #include "common/bit_util.h" | ||||
| #include "common/common_types.h" | ||||
| #include "video_core/engines/draw_manager.h" | ||||
|  | @ -116,11 +116,11 @@ struct HostSyncValues { | |||
| class SamplesStreamer : public BaseStreamer { | ||||
| public: | ||||
|     explicit SamplesStreamer(size_t id_, QueryCacheRuntime& runtime_, | ||||
|                              VideoCore::RasterizerInterface* rasterizer_, const Device& device_, | ||||
|                              VideoCore::RasterizerInterface* rasterizer_, TextureCache& texture_cache_, const Device& device_, | ||||
|                              Scheduler& scheduler_, const MemoryAllocator& memory_allocator_, | ||||
|                              ComputePassDescriptorQueue& compute_pass_descriptor_queue, | ||||
|                              DescriptorPool& descriptor_pool) | ||||
|         : BaseStreamer(id_), runtime{runtime_}, rasterizer{rasterizer_}, device{device_}, | ||||
|         : BaseStreamer(id_), texture_cache{texture_cache_}, runtime{runtime_}, rasterizer{rasterizer_}, device{device_}, | ||||
|           scheduler{scheduler_}, memory_allocator{memory_allocator_} { | ||||
|         current_bank = nullptr; | ||||
|         current_query = nullptr; | ||||
|  | @ -153,16 +153,33 @@ public: | |||
|         if (has_started) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         ReserveHostQuery(); | ||||
| 
 | ||||
|         // Ensure outside render pass
 | ||||
|         scheduler.RequestOutsideRenderPassOperationContext(); | ||||
| 
 | ||||
|         // Reset query pool outside render pass
 | ||||
|         scheduler.Record([query_pool = current_query_pool, | ||||
|                           query_index = current_bank_slot](vk::CommandBuffer cmdbuf) { | ||||
|                                  query_index = current_bank_slot](vk::CommandBuffer cmdbuf) { | ||||
|             cmdbuf.ResetQueryPool(query_pool, static_cast<u32>(query_index), 1); | ||||
|         }); | ||||
| 
 | ||||
|         // Manually restart the render pass (required for vkCmdClearAttachments, etc.)
 | ||||
|         scheduler.RequestRenderpass(texture_cache.GetFramebuffer()); | ||||
| 
 | ||||
|         // Begin query inside the newly started render pass
 | ||||
|         scheduler.Record([query_pool = current_query_pool, | ||||
|                                  query_index = current_bank_slot](vk::CommandBuffer cmdbuf) { | ||||
|             const bool use_precise = Settings::IsGPULevelHigh(); | ||||
|             cmdbuf.BeginQuery(query_pool, static_cast<u32>(query_index), | ||||
|                               use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0); | ||||
|         }); | ||||
| 
 | ||||
|         has_started = true; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void PauseCounter() override { | ||||
|         if (!has_started) { | ||||
|             return; | ||||
|  | @ -404,7 +421,7 @@ private: | |||
|             size_slots -= amount; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     TextureCache& texture_cache; | ||||
|     template <bool is_ordered, typename Func> | ||||
|     void ApplyBanksWideOp(std::vector<size_t>& queries, Func&& func) { | ||||
|         std::conditional_t<is_ordered, std::map<size_t, std::pair<size_t, size_t>>, | ||||
|  | @ -1163,13 +1180,13 @@ struct QueryCacheRuntimeImpl { | |||
|                           const MemoryAllocator& memory_allocator_, Scheduler& scheduler_, | ||||
|                           StagingBufferPool& staging_pool_, | ||||
|                           ComputePassDescriptorQueue& compute_pass_descriptor_queue, | ||||
|                           DescriptorPool& descriptor_pool) | ||||
|                           DescriptorPool& descriptor_pool, TextureCache& texture_cache_) | ||||
|         : rasterizer{rasterizer_}, device_memory{device_memory_}, buffer_cache{buffer_cache_}, | ||||
|           device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, | ||||
|           staging_pool{staging_pool_}, guest_streamer(0, runtime), | ||||
|           sample_streamer(static_cast<size_t>(QueryType::ZPassPixelCount64), runtime, rasterizer, | ||||
|                           device, scheduler, memory_allocator, compute_pass_descriptor_queue, | ||||
|                           descriptor_pool), | ||||
|                           texture_cache_, device, scheduler, memory_allocator, | ||||
|                           compute_pass_descriptor_queue, descriptor_pool), | ||||
|           tfb_streamer(static_cast<size_t>(QueryType::StreamingByteCount), runtime, device, | ||||
|                        scheduler, memory_allocator, staging_pool), | ||||
|           primitives_succeeded_streamer( | ||||
|  | @ -1240,10 +1257,10 @@ QueryCacheRuntime::QueryCacheRuntime(VideoCore::RasterizerInterface* rasterizer, | |||
|                                      const MemoryAllocator& memory_allocator_, | ||||
|                                      Scheduler& scheduler_, StagingBufferPool& staging_pool_, | ||||
|                                      ComputePassDescriptorQueue& compute_pass_descriptor_queue, | ||||
|                                      DescriptorPool& descriptor_pool) { | ||||
|                                      DescriptorPool& descriptor_pool, TextureCache& texture_cache_) { | ||||
|     impl = std::make_unique<QueryCacheRuntimeImpl>( | ||||
|         *this, rasterizer, device_memory_, buffer_cache_, device_, memory_allocator_, scheduler_, | ||||
|         staging_pool_, compute_pass_descriptor_queue, descriptor_pool); | ||||
|         staging_pool_, compute_pass_descriptor_queue, descriptor_pool, texture_cache_); | ||||
| } | ||||
| 
 | ||||
| void QueryCacheRuntime::Bind3DEngine(Maxwell3D* maxwell3d) { | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ | |||
| 
 | ||||
| #include "video_core/query_cache/query_cache_base.h" | ||||
| #include "video_core/renderer_vulkan/vk_buffer_cache.h" | ||||
| 
 | ||||
| #include "video_core/renderer_vulkan/vk_texture_cache.h" | ||||
| namespace VideoCore { | ||||
| class RasterizerInterface; | ||||
| } | ||||
|  | @ -17,7 +17,6 @@ class StreamerInterface; | |||
| } | ||||
| 
 | ||||
| namespace Vulkan { | ||||
| 
 | ||||
| class Device; | ||||
| class Scheduler; | ||||
| class StagingBufferPool; | ||||
|  | @ -32,7 +31,7 @@ public: | |||
|                                const MemoryAllocator& memory_allocator_, Scheduler& scheduler_, | ||||
|                                StagingBufferPool& staging_pool_, | ||||
|                                ComputePassDescriptorQueue& compute_pass_descriptor_queue, | ||||
|                                DescriptorPool& descriptor_pool); | ||||
|                                DescriptorPool& descriptor_pool, TextureCache& texture_cache_); | ||||
|     ~QueryCacheRuntime(); | ||||
| 
 | ||||
|     template <typename SyncValuesType> | ||||
|  |  | |||
|  | @ -189,7 +189,7 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra | |||
|                            guest_descriptor_queue, compute_pass_descriptor_queue, descriptor_pool), | ||||
|       buffer_cache(device_memory, buffer_cache_runtime), | ||||
|       query_cache_runtime(this, device_memory, buffer_cache, device, memory_allocator, scheduler, | ||||
|                           staging_pool, compute_pass_descriptor_queue, descriptor_pool), | ||||
|                           staging_pool, compute_pass_descriptor_queue, descriptor_pool, texture_cache), | ||||
|       query_cache(gpu, *this, device_memory, query_cache_runtime), | ||||
|       pipeline_cache(device_memory, device, scheduler, descriptor_pool, guest_descriptor_queue, | ||||
|                      render_pass_cache, buffer_cache, texture_cache, gpu.ShaderNotify()), | ||||
|  |  | |||
|  | @ -136,7 +136,6 @@ public: | |||
|     void BindChannel(Tegra::Control::ChannelState& channel) override; | ||||
| 
 | ||||
|     void ReleaseChannel(s32 channel_id) override; | ||||
| 
 | ||||
|     std::optional<FramebufferTextureInfo> AccelerateDisplay(const Tegra::FramebufferConfig& config, | ||||
|                                                             VAddr framebuffer_addr, | ||||
|                                                             u32 pixel_stride); | ||||
|  | @ -147,7 +146,6 @@ private: | |||
|         0x0100E95004038000ULL, // XC2
 | ||||
|         0x0100A6301214E000ULL, // FE:Engage
 | ||||
|     }; | ||||
| 
 | ||||
|     static constexpr size_t MAX_TEXTURES = 192; | ||||
|     static constexpr size_t MAX_IMAGES = 48; | ||||
|     static constexpr size_t MAX_IMAGE_VIEWS = MAX_TEXTURES + MAX_IMAGES; | ||||
|  |  | |||
|  | @ -270,46 +270,73 @@ void Scheduler::EndPendingOperations() { | |||
|     EndRenderPass(); | ||||
| } | ||||
| 
 | ||||
| void Scheduler::EndRenderPass() { | ||||
|     if (!state.renderpass) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     query_cache->CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, false); | ||||
|     query_cache->NotifySegment(false); | ||||
| 
 | ||||
|     Record([num_images = num_renderpass_images, images = renderpass_images, | ||||
|             ranges = renderpass_image_ranges](vk::CommandBuffer cmdbuf) { | ||||
|         std::array<VkImageMemoryBarrier, 9> barriers; | ||||
|         for (size_t i = 0; i < num_images; ++i) { | ||||
|             barriers[i] = VkImageMemoryBarrier{ | ||||
|                 .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||||
|                 .pNext = nullptr, | ||||
|                 .srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | | ||||
|                                  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, | ||||
|                 .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | | ||||
|                                  VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | | ||||
|                                  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | | ||||
|                                  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | | ||||
|                                  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, | ||||
|                 .oldLayout = VK_IMAGE_LAYOUT_GENERAL, | ||||
|                 .newLayout = VK_IMAGE_LAYOUT_GENERAL, | ||||
|                 .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||||
|                 .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||||
|                 .image = images[i], | ||||
|                 .subresourceRange = ranges[i], | ||||
|             }; | ||||
|     void Scheduler::EndRenderPass() { | ||||
|         if (!state.renderpass) { | ||||
|             return; | ||||
|         } | ||||
|         cmdbuf.EndRenderPass(); | ||||
|         cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | | ||||
|                                    VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | | ||||
|                                    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, | ||||
|                                VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, nullptr, nullptr, | ||||
|                                vk::Span(barriers.data(), num_images)); | ||||
|     }); | ||||
|     state.renderpass = nullptr; | ||||
|     num_renderpass_images = 0; | ||||
| } | ||||
| 
 | ||||
|         query_cache->CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, false); | ||||
|         query_cache->NotifySegment(false); | ||||
| 
 | ||||
|         Record([num_images = num_renderpass_images, images = renderpass_images, | ||||
|                        ranges = renderpass_image_ranges](vk::CommandBuffer cmdbuf) { | ||||
|             std::array<VkImageMemoryBarrier, 9> barriers; | ||||
|             VkPipelineStageFlags src_stages = 0; | ||||
| 
 | ||||
|             for (size_t i = 0; i < num_images; ++i) { | ||||
|                 const VkImageSubresourceRange& range = ranges[i]; | ||||
|                 const bool is_color = range.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT; | ||||
|                 const bool is_depth_stencil = range.aspectMask & | ||||
|                                               (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT); | ||||
| 
 | ||||
|                 VkAccessFlags src_access = 0; | ||||
|                 VkPipelineStageFlags this_stage = 0; | ||||
| 
 | ||||
|                 if (is_color) { | ||||
|                     src_access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; | ||||
|                     this_stage |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; | ||||
|                 } | ||||
| 
 | ||||
|                 if (is_depth_stencil) { | ||||
|                     src_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; | ||||
|                     this_stage |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | | ||||
|                                   VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; | ||||
|                 } | ||||
| 
 | ||||
|                 src_stages |= this_stage; | ||||
| 
 | ||||
|                 barriers[i] = VkImageMemoryBarrier{ | ||||
|                         .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||||
|                         .pNext = nullptr, | ||||
|                         .srcAccessMask = src_access, | ||||
|                         .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT | | ||||
|                                          VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | | ||||
|                                          VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | | ||||
|                                          VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | | ||||
|                                          VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, | ||||
|                         .oldLayout = VK_IMAGE_LAYOUT_GENERAL, | ||||
|                         .newLayout = VK_IMAGE_LAYOUT_GENERAL, | ||||
|                         .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||||
|                         .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||||
|                         .image = images[i], | ||||
|                         .subresourceRange = range, | ||||
|                 }; | ||||
|             } | ||||
| 
 | ||||
|             cmdbuf.EndRenderPass(); | ||||
| 
 | ||||
|             for (size_t i = 0; i < num_images; ++i) { | ||||
|                 cmdbuf.PipelineBarrier( | ||||
|                         src_stages, // OR compute per-image if needed
 | ||||
|                         VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, | ||||
|                         0, | ||||
|                         barriers[i]); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         state.renderpass = nullptr; | ||||
|         num_renderpass_images = 0; | ||||
|     } | ||||
| 
 | ||||
| void Scheduler::AcquireNewChunk() { | ||||
|     std::scoped_lock rl{reserve_mutex}; | ||||
|  |  | |||
|  | @ -508,58 +508,84 @@ TransformBufferCopies(std::span<const VideoCommon::BufferCopy> copies, size_t bu | |||
|         return value; | ||||
|     } | ||||
| } | ||||
| struct RangedBarrierRange { | ||||
|     u32 min_mip = std::numeric_limits<u32>::max(); | ||||
|     u32 max_mip = std::numeric_limits<u32>::min(); | ||||
|     u32 min_layer = std::numeric_limits<u32>::max(); | ||||
|     u32 max_layer = std::numeric_limits<u32>::min(); | ||||
| 
 | ||||
|     void AddLayers(const VkImageSubresourceLayers& layers) { | ||||
|         min_mip = std::min(min_mip, layers.mipLevel); | ||||
|         max_mip = std::max(max_mip, layers.mipLevel + 1); | ||||
|         min_layer = std::min(min_layer, layers.baseArrayLayer); | ||||
|         max_layer = std::max(max_layer, layers.baseArrayLayer + layers.layerCount); | ||||
|     } | ||||
| 
 | ||||
|     VkImageSubresourceRange SubresourceRange(VkImageAspectFlags aspect_mask) const noexcept { | ||||
|         return VkImageSubresourceRange{ | ||||
|             .aspectMask = aspect_mask, | ||||
|             .baseMipLevel = min_mip, | ||||
|             .levelCount = max_mip - min_mip, | ||||
|             .baseArrayLayer = min_layer, | ||||
|             .layerCount = max_layer - min_layer, | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
| void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage image, | ||||
|                        VkImageAspectFlags aspect_mask, bool is_initialized, | ||||
|                        std::span<const VkBufferImageCopy> copies) { | ||||
|     static constexpr VkAccessFlags WRITE_ACCESS_FLAGS = | ||||
|         VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | | ||||
|         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; | ||||
|                                            VK_ACCESS_SHADER_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | | ||||
|                                            VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; | ||||
|     static constexpr VkAccessFlags READ_ACCESS_FLAGS = VK_ACCESS_SHADER_READ_BIT | | ||||
|                                                        VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | | ||||
|                                                        VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; | ||||
| 
 | ||||
|     //  Compute exact mip/layer range being written to
 | ||||
|     RangedBarrierRange range; | ||||
|     for (const auto& region : copies) { | ||||
|         range.AddLayers(region.imageSubresource); | ||||
|     } | ||||
|     const VkImageSubresourceRange subresource_range = range.SubresourceRange(aspect_mask); | ||||
| 
 | ||||
|     const VkImageMemoryBarrier read_barrier{ | ||||
|         .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||||
|         .pNext = nullptr, | ||||
|         .srcAccessMask = WRITE_ACCESS_FLAGS, | ||||
|         .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, | ||||
|         .oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED, | ||||
|         .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | ||||
|         .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||||
|         .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||||
|         .image = image, | ||||
|         .subresourceRange{ | ||||
|             .aspectMask = aspect_mask, | ||||
|             .baseMipLevel = 0, | ||||
|             .levelCount = VK_REMAINING_MIP_LEVELS, | ||||
|             .baseArrayLayer = 0, | ||||
|             .layerCount = VK_REMAINING_ARRAY_LAYERS, | ||||
|         }, | ||||
|             .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||||
|             .pNext = nullptr, | ||||
|             .srcAccessMask = WRITE_ACCESS_FLAGS, | ||||
|             .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, | ||||
|             .oldLayout = is_initialized ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_UNDEFINED, | ||||
|             .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | ||||
|             .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||||
|             .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||||
|             .image = image, | ||||
|             .subresourceRange = subresource_range, | ||||
|     }; | ||||
| 
 | ||||
|     const VkImageMemoryBarrier write_barrier{ | ||||
|         .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||||
|         .pNext = nullptr, | ||||
|         .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, | ||||
|         .dstAccessMask = WRITE_ACCESS_FLAGS | READ_ACCESS_FLAGS, | ||||
|         .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | ||||
|         .newLayout = VK_IMAGE_LAYOUT_GENERAL, | ||||
|         .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||||
|         .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||||
|         .image = image, | ||||
|         .subresourceRange{ | ||||
|             .aspectMask = aspect_mask, | ||||
|             .baseMipLevel = 0, | ||||
|             .levelCount = VK_REMAINING_MIP_LEVELS, | ||||
|             .baseArrayLayer = 0, | ||||
|             .layerCount = VK_REMAINING_ARRAY_LAYERS, | ||||
|         }, | ||||
|             .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, | ||||
|             .pNext = nullptr, | ||||
|             .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT, | ||||
|             .dstAccessMask = WRITE_ACCESS_FLAGS | READ_ACCESS_FLAGS, | ||||
|             .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, | ||||
|             .newLayout = VK_IMAGE_LAYOUT_GENERAL, | ||||
|             .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||||
|             .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, | ||||
|             .image = image, | ||||
|             .subresourceRange = subresource_range, | ||||
|     }; | ||||
|     cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, | ||||
| 
 | ||||
|     cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | | ||||
|                            VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | | ||||
|                            VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, | ||||
|                            read_barrier); | ||||
|     cmdbuf.CopyBufferToImage(src_buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, copies); | ||||
|     // TODO: Move this to another API
 | ||||
|     cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, | ||||
|                            write_barrier); | ||||
|     cmdbuf.PipelineBarrier( | ||||
|             VK_PIPELINE_STAGE_TRANSFER_BIT, | ||||
|             VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | | ||||
|             VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | | ||||
|             VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, | ||||
|             0, nullptr, nullptr, write_barrier); | ||||
| } | ||||
| 
 | ||||
| [[nodiscard]] VkImageBlit MakeImageBlit(const Region2D& dst_region, const Region2D& src_region, | ||||
|  | @ -652,29 +678,7 @@ void TryTransformSwizzleIfNeeded(PixelFormat format, std::array<SwizzleSource, 4 | |||
|     } | ||||
| } | ||||
| 
 | ||||
| struct RangedBarrierRange { | ||||
|     u32 min_mip = std::numeric_limits<u32>::max(); | ||||
|     u32 max_mip = std::numeric_limits<u32>::min(); | ||||
|     u32 min_layer = std::numeric_limits<u32>::max(); | ||||
|     u32 max_layer = std::numeric_limits<u32>::min(); | ||||
| 
 | ||||
|     void AddLayers(const VkImageSubresourceLayers& layers) { | ||||
|         min_mip = std::min(min_mip, layers.mipLevel); | ||||
|         max_mip = std::max(max_mip, layers.mipLevel + 1); | ||||
|         min_layer = std::min(min_layer, layers.baseArrayLayer); | ||||
|         max_layer = std::max(max_layer, layers.baseArrayLayer + layers.layerCount); | ||||
|     } | ||||
| 
 | ||||
|     VkImageSubresourceRange SubresourceRange(VkImageAspectFlags aspect_mask) const noexcept { | ||||
|         return VkImageSubresourceRange{ | ||||
|             .aspectMask = aspect_mask, | ||||
|             .baseMipLevel = min_mip, | ||||
|             .levelCount = max_mip - min_mip, | ||||
|             .baseArrayLayer = min_layer, | ||||
|             .layerCount = max_layer - min_layer, | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| [[nodiscard]] VkFormat Format(Shader::ImageFormat format) { | ||||
|     switch (format) { | ||||
|  | @ -1458,12 +1462,18 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src, | |||
|                 .subresourceRange = dst_range.SubresourceRange(aspect_mask), | ||||
|             }, | ||||
|         }; | ||||
|         cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, | ||||
|                                0, {}, {}, pre_barriers); | ||||
|         cmdbuf.PipelineBarrier( | ||||
|                 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | | ||||
|                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, | ||||
|                 VK_PIPELINE_STAGE_TRANSFER_BIT, | ||||
|                 0, nullptr, nullptr, pre_barriers); | ||||
|         cmdbuf.CopyImage(src_image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dst_image, | ||||
|                          VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, vk_copies); | ||||
|         cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, | ||||
|                                0, {}, {}, post_barriers); | ||||
|         cmdbuf.PipelineBarrier( | ||||
|                 VK_PIPELINE_STAGE_TRANSFER_BIT, | ||||
|                 VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | | ||||
|                 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT, | ||||
|                 0, nullptr, nullptr, post_barriers); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
|  | @ -2377,7 +2387,7 @@ void TextureCacheRuntime::TransitionImageLayout(Image& image) { | |||
|         }; | ||||
|         scheduler.RequestOutsideRenderPassOperationContext(); | ||||
|         scheduler.Record([barrier](vk::CommandBuffer cmdbuf) { | ||||
|             cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, | ||||
|             cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, | ||||
|                                    VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, barrier); | ||||
|         }); | ||||
|     } | ||||
|  |  | |||
|  | @ -120,6 +120,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { | |||
|     X(vkCmdEndConditionalRenderingEXT); | ||||
|     X(vkCmdEndQuery); | ||||
|     X(vkCmdEndRenderPass); | ||||
|     X(vkCmdResetQueryPool); | ||||
|     X(vkCmdEndTransformFeedbackEXT); | ||||
|     X(vkCmdEndDebugUtilsLabelEXT); | ||||
|     X(vkCmdFillBuffer); | ||||
|  |  | |||
|  | @ -219,6 +219,7 @@ struct DeviceDispatch : InstanceDispatch { | |||
|     PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT{}; | ||||
|     PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT{}; | ||||
|     PFN_vkCmdEndQuery vkCmdEndQuery{}; | ||||
|     PFN_vkCmdResetQueryPool vkCmdResetQueryPool{}; | ||||
|     PFN_vkCmdEndRenderPass vkCmdEndRenderPass{}; | ||||
|     PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT{}; | ||||
|     PFN_vkCmdFillBuffer vkCmdFillBuffer{}; | ||||
|  | @ -1137,7 +1138,9 @@ public: | |||
|     VkCommandBuffer operator*() const noexcept { | ||||
|         return handle; | ||||
|     } | ||||
| 
 | ||||
|     void ResetQueryPool(VkQueryPool query_pool, uint32_t first, uint32_t count) const noexcept { | ||||
|         dld->vkCmdResetQueryPool(handle, query_pool, first, count); | ||||
|     } | ||||
|     void Begin(const VkCommandBufferBeginInfo& begin_info) const { | ||||
|         Check(dld->vkBeginCommandBuffer(handle, &begin_info)); | ||||
|     } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Shinmegumi
						Shinmegumi