From 7e1c58acccbffdda3b94782562d1deac6ad294c0 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Sat, 4 Feb 2023 22:32:36 +0000 Subject: [PATCH] Implement indirect draws in the Maxwell 3D interconnect These will be used by the HLE indirect draw macro to perform indirect draws without waiting for GPU idle. --- .../interconnect/maxwell_3d/maxwell_3d.cpp | 63 +++++++++++++++++++ .../gpu/interconnect/maxwell_3d/maxwell_3d.h | 3 + 2 files changed, 66 insertions(+) diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.cpp b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.cpp index 3dfc68a5..a021f150 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.cpp @@ -352,4 +352,67 @@ namespace skyline::gpu::interconnect::maxwell3d { }, scissor, activeDescriptorSetSampledImages, {}, activeState.GetColorAttachments(), activeState.GetDepthAttachment(), !ctx.gpu.traits.quirks.relaxedRenderPassCompatibility, srcStageMask, dstStageMask); ctx.executor.AddCheckpoint("After draw"); } + + void Maxwell3D::DrawIndirect(engine::DrawTopology topology, bool transformFeedbackEnable, bool indexed, span indirectBuffer, u32 count, u32 stride) { + if (!count) + return; + + TRACE_EVENT("gpu", "Indirect Draw", "buffer", reinterpret_cast(indirectBuffer.data())); + + StateUpdateBuilder builder{*ctx.executor.allocator}; + vk::PipelineStageFlags srcStageMask{}, dstStageMask{}; + + PrepareDraw(builder, topology, indexed, true, 0, 0, srcStageMask, dstStageMask); + + if (directState.inputAssembly.NeedsQuadConversion()) + throw exception("Quad conversion is not supported for indirect draws!"); + + if (indirectBufferView) + indirectBufferView = indirectBufferView.GetBuffer()->TryGetView(indirectBuffer); + if (!indirectBufferView) + indirectBufferView = ctx.gpu.buffer.FindOrCreate(indirectBuffer, ctx.executor.tag, [this](std::shared_ptr buffer, ContextLock &&lock) { + ctx.executor.AttachLockedBuffer(buffer, std::move(lock)); + }); + + indirectBufferView.GetBuffer()->BlockSequencedCpuBackingWrites(); + + auto stateUpdater{builder.Build()}; + + /** + * @brief Struct that can be linearly allocated, holding all state for the draw to avoid a dynamic allocation with lambda captures + */ + struct DrawParams { + StateUpdater stateUpdater; + BufferView indirectBuffer; + u32 count; + u32 stride; + bool indexed; + bool transformFeedbackEnable; + }; + auto *drawParams{ctx.executor.allocator->EmplaceUntracked(DrawParams{stateUpdater, + indirectBufferView, + count, stride, indexed, + ctx.gpu.traits.supportsTransformFeedback ? transformFeedbackEnable : false})}; + + auto scissor{GetDrawScissor()}; + constantBuffers.ResetQuickBind(); + + ctx.executor.AddCheckpoint("Before indirect draw"); + ctx.executor.AddSubpass([drawParams](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &, GPU &gpu, vk::RenderPass, u32) { + drawParams->stateUpdater.RecordAll(gpu, commandBuffer); + + if (drawParams->transformFeedbackEnable) + commandBuffer.beginTransformFeedbackEXT(0, {}, {}); + + auto indirectBinding{drawParams->indirectBuffer.GetBinding(gpu)}; + if (drawParams->indexed) + commandBuffer.drawIndexedIndirect(indirectBinding.buffer, indirectBinding.offset, drawParams->count, drawParams->stride); + else + commandBuffer.drawIndirect(indirectBinding.buffer, indirectBinding.offset, drawParams->count, drawParams->stride); + + if (drawParams->transformFeedbackEnable) + commandBuffer.endTransformFeedbackEXT(0, {}, {}); + }, scissor, activeDescriptorSetSampledImages, {}, activeState.GetColorAttachments(), activeState.GetDepthAttachment(), !ctx.gpu.traits.quirks.relaxedRenderPassCompatibility, srcStageMask, dstStageMask); + ctx.executor.AddCheckpoint("After indirect draw"); + } } \ No newline at end of file diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.h b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.h index 36627d92..ca095a58 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/maxwell_3d.h @@ -49,6 +49,7 @@ namespace skyline::gpu::interconnect::maxwell3d { Textures textures; std::shared_ptr quadConversionBuffer{}; bool quadConversionBufferAttached{}; + BufferView indirectBufferView; static constexpr size_t DescriptorBatchSize{0x100}; std::shared_ptr> attachedDescriptorSets; @@ -102,5 +103,7 @@ namespace skyline::gpu::interconnect::maxwell3d { void Clear(engine::ClearSurface &clearSurface); void Draw(engine::DrawTopology topology, bool transformFeedbackEnable, bool indexed, u32 count, u32 first, u32 instanceCount, u32 vertexOffset, u32 firstInstance); + + void DrawIndirect(engine::DrawTopology topology, bool transformFeedbackEnable, bool indexed, span indirectBuffer, u32 count, u32 stride); }; }