video_core: added support for indirect draws (#678)

* video_core: added support for indirect draws

* barriers simplified
This commit is contained in:
psucien 2024-08-30 22:59:56 +02:00 committed by GitHub
parent 3d375a28eb
commit ca1613258f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 140 additions and 35 deletions

View file

@ -29,6 +29,19 @@ Rasterizer::Rasterizer(const Instance& instance_, Scheduler& scheduler_,
Rasterizer::~Rasterizer() = default;
void Rasterizer::CpSync() {
scheduler.EndRendering();
auto cmdbuf = scheduler.CommandBuffer();
const vk::MemoryBarrier ib_barrier{
.srcAccessMask = vk::AccessFlagBits::eShaderWrite,
.dstAccessMask = vk::AccessFlagBits::eIndirectCommandRead,
};
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eComputeShader,
vk::PipelineStageFlagBits::eDrawIndirect,
vk::DependencyFlagBits::eByRegion, ib_barrier, {}, {});
}
void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
RENDERER_TRACE;
@ -66,6 +79,45 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
}
}
void Rasterizer::DrawIndirect(bool is_indexed, VAddr address, u32 offset, u32 size) {
RENDERER_TRACE;
const auto cmdbuf = scheduler.CommandBuffer();
const auto& regs = liverpool->regs;
const GraphicsPipeline* pipeline = pipeline_cache.GetGraphicsPipeline();
if (!pipeline) {
return;
}
ASSERT_MSG(regs.primitive_type != AmdGpu::Liverpool::PrimitiveType::RectList,
"Unsupported primitive type for indirect draw");
try {
pipeline->BindResources(regs, buffer_cache, texture_cache);
} catch (...) {
UNREACHABLE();
}
const auto& vs_info = pipeline->GetStage(Shader::Stage::Vertex);
buffer_cache.BindVertexBuffers(vs_info);
const u32 num_indices = buffer_cache.BindIndexBuffer(is_indexed, 0);
BeginRendering();
UpdateDynamicState(*pipeline);
const auto [buffer, base] = buffer_cache.ObtainBuffer(address, size, true);
const auto total_offset = base + offset;
// We can safely ignore both SGPR UD indices and results of fetch shader parsing, as vertex and
// instance offsets will be automatically applied by Vulkan from indirect args buffer.
if (is_indexed) {
cmdbuf.drawIndexedIndirect(buffer->Handle(), total_offset, 1, 0);
} else {
cmdbuf.drawIndirect(buffer->Handle(), total_offset, 1, 0);
}
}
void Rasterizer::DispatchDirect() {
RENDERER_TRACE;
@ -113,19 +165,6 @@ void Rasterizer::DispatchIndirect(VAddr address, u32 offset, u32 size) {
cmdbuf.bindPipeline(vk::PipelineBindPoint::eCompute, pipeline->Handle());
const auto [buffer, base] = buffer_cache.ObtainBuffer(address, size, true);
const auto total_offset = base + offset;
// Emulate PFP-to-ME sync packet
const vk::BufferMemoryBarrier ib_barrier{
.srcAccessMask = vk::AccessFlagBits::eShaderWrite,
.dstAccessMask = vk::AccessFlagBits::eIndirectCommandRead,
.buffer = buffer->Handle(),
.offset = total_offset,
.size = size,
};
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eComputeShader,
vk::PipelineStageFlagBits::eDrawIndirect,
vk::DependencyFlagBits::eByRegion, {}, ib_barrier, {});
cmdbuf.dispatchIndirect(buffer->Handle(), total_offset);
}

View file

@ -32,6 +32,7 @@ public:
}
void Draw(bool is_indexed, u32 index_offset = 0);
void DrawIndirect(bool is_indexed, VAddr address, u32 offset, u32 size);
void DispatchDirect();
void DispatchIndirect(VAddr address, u32 offset, u32 size);
@ -45,6 +46,7 @@ public:
void MapMemory(VAddr addr, u64 size);
void UnmapMemory(VAddr addr, u64 size);
void CpSync();
u64 Flush();
private: