diff --git a/src/graphics/guest_gpu/graphicsRun.cpp b/src/graphics/guest_gpu/graphicsRun.cpp index 001a7794f..92c010e1c 100644 --- a/src/graphics/guest_gpu/graphicsRun.cpp +++ b/src/graphics/guest_gpu/graphicsRun.cpp @@ -313,7 +313,7 @@ void CommandProcessor::Reset() { m_ucfg.Reset(); m_ctx.Reset(); m_saved_ctx.Reset(); - m_context_state_pushed = false; + m_context_state_pushed = false; m_index_type_and_size = 0; m_index_buffer_size = 0; m_user_data_marker = HW::UserSgprType::Unknown; @@ -1176,9 +1176,9 @@ void CommandProcessor::DrawIndirectMulti(uint32_t data_offset, uint32_t max_coun void CommandProcessor::DispatchDirect(uint32_t thread_group_x, uint32_t thread_group_y, uint32_t thread_group_z, uint32_t mode) { uint32_t frame_num = 0; - uint32_t local_x = 1; - uint32_t local_y = 1; - uint32_t local_z = 1; + // uint32_t local_x = 1; + // uint32_t local_y = 1; + // uint32_t local_z = 1; { CheckBuffer(); @@ -1202,9 +1202,9 @@ void CommandProcessor::DispatchDirect(uint32_t thread_group_x, uint32_t thread_g } const auto& cs = m_sh_ctx.GetCs().cs_regs; - local_x = std::max(cs.num_thread_x, 1u); - local_y = std::max(cs.num_thread_y, 1u); - local_z = std::max(cs.num_thread_z, 1u); + // local_x = std::max(cs.num_thread_x, 1u); + // local_y = std::max(cs.num_thread_y, 1u); + // local_z = std::max(cs.num_thread_z, 1u); if (cs.wave_size == 64u) { static std::atomic_bool logged_wave64_shader {false}; if (!logged_wave64_shader.exchange(true, std::memory_order_relaxed)) { @@ -1220,27 +1220,27 @@ void CommandProcessor::DispatchDirect(uint32_t thread_group_x, uint32_t thread_g thread_group_y, thread_group_z, mode); } - constexpr uint32_t DispatchInitiatorUseThreadDimensions = 1u << 5u; + /*constexpr uint32_t DispatchInitiatorUseThreadDimensions = 1u << 5u; auto group_count = [](uint32_t threads, uint32_t group_size) { - return (threads == 0 - ? 0u - : (threads + std::max(group_size, 1u) - 1u) / std::max(group_size, 1u)); + return (threads == 0 + ? 0u + : (threads + std::max(group_size, 1u) - 1u) / std::max(group_size, 1u)); }; auto groups_x = thread_group_x; auto groups_y = thread_group_y; auto groups_z = thread_group_z; if ((mode & DispatchInitiatorUseThreadDimensions) != 0) { - groups_x = group_count(thread_group_x, local_x); - groups_y = group_count(thread_group_y, local_y); - groups_z = group_count(thread_group_z, local_z); + groups_x = group_count(thread_group_x, local_x); + groups_y = group_count(thread_group_y, local_y); + groups_z = group_count(thread_group_z, local_z); } const uint64_t invocations = static_cast(groups_x) * groups_y * groups_z * local_x * local_y * local_z; if (invocations != 0) { - BufferFlushAndWait(); - } + BufferFlushAndWait(); + }*/ } void CommandProcessor::DispatchIndirect(uint32_t data_offset, uint32_t mode) { diff --git a/src/graphics/host_gpu/renderer/pipeline/shaderResourceBarrier.cpp b/src/graphics/host_gpu/renderer/pipeline/shaderResourceBarrier.cpp index 254c6adea..fdd0ea815 100644 --- a/src/graphics/host_gpu/renderer/pipeline/shaderResourceBarrier.cpp +++ b/src/graphics/host_gpu/renderer/pipeline/shaderResourceBarrier.cpp @@ -36,6 +36,22 @@ VulkanMemoryBarrier MakeShaderWriteDependency() { return barrier; } +VulkanMemoryBarrier MakeShaderAccessDependency() { + VulkanMemoryBarrier barrier {}; + barrier.sType = vk::StructureType::eMemoryBarrier; + barrier.srcAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite; + barrier.dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite; + return barrier; +} + +VulkanMemoryBarrier MakeShaderWriteHazardDependency() { + VulkanMemoryBarrier barrier {}; + barrier.sType = vk::StructureType::eMemoryBarrier; + barrier.srcAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite; + barrier.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite; + return barrier; +} + vk::BufferMemoryBarrier MakeGdsDependency(vk::Buffer buffer) { EXIT_IF(buffer == nullptr); @@ -84,6 +100,21 @@ bool HasShaderBufferWrites(const ShaderStageRuntime& runtime) { return !CollectShaderBufferWrites(*runtime.program, *runtime.resources).empty(); } +void ShaderAccessBarrier(vk::CommandBuffer vk_buffer, vk::PipelineStageFlags source_stages) { + EXIT_IF(vk_buffer == nullptr || !source_stages); + const auto barrier = MakeShaderAccessDependency(); + vk_buffer.pipelineBarrier(source_stages, vk::PipelineStageFlagBits::eAllCommands, + vk::DependencyFlags {}, 1, &barrier, 0, nullptr, 0, nullptr); +} + +void ShaderWriteHazardBarrier(vk::CommandBuffer vk_buffer, + vk::PipelineStageFlags destination_stages) { + EXIT_IF(vk_buffer == nullptr || !destination_stages); + const auto barrier = MakeShaderWriteHazardDependency(); + vk_buffer.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands, destination_stages, + vk::DependencyFlags {}, 1, &barrier, 0, nullptr, 0, nullptr); +} + void ShaderWriteBarrier(vk::CommandBuffer vk_buffer, vk::PipelineStageFlags source_stages) { EXIT_IF(vk_buffer == nullptr || !source_stages); const auto barrier = MakeShaderWriteDependency(); diff --git a/src/graphics/host_gpu/renderer/pipeline/shaderResourceBarrier.h b/src/graphics/host_gpu/renderer/pipeline/shaderResourceBarrier.h index 4744a7783..a68b295a5 100644 --- a/src/graphics/host_gpu/renderer/pipeline/shaderResourceBarrier.h +++ b/src/graphics/host_gpu/renderer/pipeline/shaderResourceBarrier.h @@ -18,12 +18,17 @@ struct ShaderBufferWriteRange { }; vk::PipelineStageFlags ShaderPipelineStages(vk::ShaderStageFlags stages); +VulkanMemoryBarrier MakeShaderAccessDependency(); +VulkanMemoryBarrier MakeShaderWriteHazardDependency(); VulkanMemoryBarrier MakeShaderWriteDependency(); vk::BufferMemoryBarrier MakeGdsDependency(vk::Buffer buffer); std::vector CollectShaderBufferWrites(const ShaderRecompiler::IR::Program& program, const ShaderRecompiler::IR::ResourceSnapshot& resources); bool HasShaderBufferWrites(const ShaderStageRuntime& runtime); +void ShaderAccessBarrier(vk::CommandBuffer vk_buffer, vk::PipelineStageFlags source_stages); +void ShaderWriteHazardBarrier(vk::CommandBuffer vk_buffer, + vk::PipelineStageFlags destination_stages); void ShaderWriteBarrier(vk::CommandBuffer vk_buffer, vk::PipelineStageFlags source_stages); } // namespace Libs::Graphics diff --git a/src/graphics/host_gpu/renderer/renderCompute.cpp b/src/graphics/host_gpu/renderer/renderCompute.cpp index 5c5a5b05f..740edb641 100644 --- a/src/graphics/host_gpu/renderer/renderCompute.cpp +++ b/src/graphics/host_gpu/renderer/renderCompute.cpp @@ -325,9 +325,6 @@ void RenderExecutor::DispatchDirect(uint64_t submit_id, RenderCommandBuffer& buf auto vk_buffer = buffer.Handle(); CommitBindings(buffer, vk::PipelineBindPoint::eCompute, pipeline.pipeline_layout, bindings); - vk_buffer.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline.pipeline); - vk_buffer.dispatch(thread_group_x, thread_group_y, thread_group_z); - bool has_storage_writes = HasShaderBufferWrites(input_info.stage); has_storage_writes = std::any_of(program.info.images.begin(), program.info.images.end(), @@ -338,8 +335,15 @@ void RenderExecutor::DispatchDirect(uint64_t submit_id, RenderCommandBuffer& buf }) || has_storage_writes; if (has_storage_writes) { - ShaderWriteBarrier(vk_buffer, vk::PipelineStageFlagBits::eComputeShader); + // A host fence used to serialize every dispatch. Preserve its read-before-write ordering + // while allowing the queue to execute asynchronously. + ShaderWriteHazardBarrier(vk_buffer, vk::PipelineStageFlagBits::eComputeShader); } + vk_buffer.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline.pipeline); + vk_buffer.dispatch(thread_group_x, thread_group_y, thread_group_z); + + // The removed host fence also ordered read-only dispatches before later writers. + ShaderAccessBarrier(vk_buffer, vk::PipelineStageFlagBits::eComputeShader); ResetBindings(); }