mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
graphics: make DispatchDirect asynchronous
This commit is contained in:
@@ -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,
|
void CommandProcessor::DispatchDirect(uint32_t thread_group_x, uint32_t thread_group_y,
|
||||||
uint32_t thread_group_z, uint32_t mode) {
|
uint32_t thread_group_z, uint32_t mode) {
|
||||||
uint32_t frame_num = 0;
|
uint32_t frame_num = 0;
|
||||||
uint32_t local_x = 1;
|
// uint32_t local_x = 1;
|
||||||
uint32_t local_y = 1;
|
// uint32_t local_y = 1;
|
||||||
uint32_t local_z = 1;
|
// uint32_t local_z = 1;
|
||||||
|
|
||||||
{
|
{
|
||||||
CheckBuffer();
|
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;
|
const auto& cs = m_sh_ctx.GetCs().cs_regs;
|
||||||
local_x = std::max(cs.num_thread_x, 1u);
|
// local_x = std::max(cs.num_thread_x, 1u);
|
||||||
local_y = std::max(cs.num_thread_y, 1u);
|
// local_y = std::max(cs.num_thread_y, 1u);
|
||||||
local_z = std::max(cs.num_thread_z, 1u);
|
// local_z = std::max(cs.num_thread_z, 1u);
|
||||||
if (cs.wave_size == 64u) {
|
if (cs.wave_size == 64u) {
|
||||||
static std::atomic_bool logged_wave64_shader {false};
|
static std::atomic_bool logged_wave64_shader {false};
|
||||||
if (!logged_wave64_shader.exchange(true, std::memory_order_relaxed)) {
|
if (!logged_wave64_shader.exchange(true, std::memory_order_relaxed)) {
|
||||||
@@ -1220,7 +1220,7 @@ void CommandProcessor::DispatchDirect(uint32_t thread_group_x, uint32_t thread_g
|
|||||||
thread_group_y, thread_group_z, mode);
|
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) {
|
auto group_count = [](uint32_t threads, uint32_t group_size) {
|
||||||
return (threads == 0
|
return (threads == 0
|
||||||
? 0u
|
? 0u
|
||||||
@@ -1240,7 +1240,7 @@ void CommandProcessor::DispatchDirect(uint32_t thread_group_x, uint32_t thread_g
|
|||||||
static_cast<uint64_t>(groups_x) * groups_y * groups_z * local_x * local_y * local_z;
|
static_cast<uint64_t>(groups_x) * groups_y * groups_z * local_x * local_y * local_z;
|
||||||
if (invocations != 0) {
|
if (invocations != 0) {
|
||||||
BufferFlushAndWait();
|
BufferFlushAndWait();
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandProcessor::DispatchIndirect(uint32_t data_offset, uint32_t mode) {
|
void CommandProcessor::DispatchIndirect(uint32_t data_offset, uint32_t mode) {
|
||||||
|
|||||||
@@ -36,6 +36,22 @@ VulkanMemoryBarrier MakeShaderWriteDependency() {
|
|||||||
return barrier;
|
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) {
|
vk::BufferMemoryBarrier MakeGdsDependency(vk::Buffer buffer) {
|
||||||
EXIT_IF(buffer == nullptr);
|
EXIT_IF(buffer == nullptr);
|
||||||
|
|
||||||
@@ -84,6 +100,21 @@ bool HasShaderBufferWrites(const ShaderStageRuntime& runtime) {
|
|||||||
return !CollectShaderBufferWrites(*runtime.program, *runtime.resources).empty();
|
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) {
|
void ShaderWriteBarrier(vk::CommandBuffer vk_buffer, vk::PipelineStageFlags source_stages) {
|
||||||
EXIT_IF(vk_buffer == nullptr || !source_stages);
|
EXIT_IF(vk_buffer == nullptr || !source_stages);
|
||||||
const auto barrier = MakeShaderWriteDependency();
|
const auto barrier = MakeShaderWriteDependency();
|
||||||
|
|||||||
@@ -18,12 +18,17 @@ struct ShaderBufferWriteRange {
|
|||||||
};
|
};
|
||||||
|
|
||||||
vk::PipelineStageFlags ShaderPipelineStages(vk::ShaderStageFlags stages);
|
vk::PipelineStageFlags ShaderPipelineStages(vk::ShaderStageFlags stages);
|
||||||
|
VulkanMemoryBarrier MakeShaderAccessDependency();
|
||||||
|
VulkanMemoryBarrier MakeShaderWriteHazardDependency();
|
||||||
VulkanMemoryBarrier MakeShaderWriteDependency();
|
VulkanMemoryBarrier MakeShaderWriteDependency();
|
||||||
vk::BufferMemoryBarrier MakeGdsDependency(vk::Buffer buffer);
|
vk::BufferMemoryBarrier MakeGdsDependency(vk::Buffer buffer);
|
||||||
std::vector<ShaderBufferWriteRange>
|
std::vector<ShaderBufferWriteRange>
|
||||||
CollectShaderBufferWrites(const ShaderRecompiler::IR::Program& program,
|
CollectShaderBufferWrites(const ShaderRecompiler::IR::Program& program,
|
||||||
const ShaderRecompiler::IR::ResourceSnapshot& resources);
|
const ShaderRecompiler::IR::ResourceSnapshot& resources);
|
||||||
bool HasShaderBufferWrites(const ShaderStageRuntime& runtime);
|
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);
|
void ShaderWriteBarrier(vk::CommandBuffer vk_buffer, vk::PipelineStageFlags source_stages);
|
||||||
|
|
||||||
} // namespace Libs::Graphics
|
} // namespace Libs::Graphics
|
||||||
|
|||||||
@@ -325,9 +325,6 @@ void RenderExecutor::DispatchDirect(uint64_t submit_id, RenderCommandBuffer& buf
|
|||||||
|
|
||||||
auto vk_buffer = buffer.Handle();
|
auto vk_buffer = buffer.Handle();
|
||||||
CommitBindings(buffer, vk::PipelineBindPoint::eCompute, pipeline.pipeline_layout, bindings);
|
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);
|
bool has_storage_writes = HasShaderBufferWrites(input_info.stage);
|
||||||
has_storage_writes =
|
has_storage_writes =
|
||||||
std::any_of(program.info.images.begin(), program.info.images.end(),
|
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;
|
has_storage_writes;
|
||||||
if (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();
|
ResetBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user