From 1c3f62b7b4ae0e022eaeea48b20cd7b97ffdc3d1 Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Fri, 24 Dec 2021 21:34:52 +0530 Subject: [PATCH] Implement Maxwell3D Indexed Drawing --- .../gpu/interconnect/graphics_context.h | 33 +++++++++++++++++-- .../skyline/soc/gm20b/engines/maxwell_3d.cpp | 6 +++- .../skyline/soc/gm20b/engines/maxwell_3d.h | 9 +++-- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h index e5b9dc81..8936b2fa 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h @@ -1626,7 +1626,8 @@ namespace skyline::gpu::interconnect { vk::raii::PipelineCache pipelineCache; public: - void Draw(u32 vertexCount, u32 firstVertex) { + template + void Draw(u32 count, u32 first, i32 vertexOffset = 0) { // Color Render Target Setup boost::container::static_vector, maxwell3d::RenderTargetCount> colorRenderTargetLocks; boost::container::static_vector activeColorRenderTargets; @@ -1696,6 +1697,19 @@ namespace skyline::gpu::interconnect { .setLayoutCount = 1, }); + vk::Buffer indexBufferHandle; + vk::DeviceSize indexBufferOffset; + vk::IndexType indexBufferType; + if constexpr (IsIndexed) { + auto indexBufferView{GetIndexBuffer(count)}; + std::scoped_lock lock(*indexBufferView); + executor.AttachBuffer(indexBufferView); + + indexBufferHandle = indexBufferView->buffer->GetBacking(); + indexBufferOffset = indexBufferView->offset; + indexBufferType = indexBuffer.type; + } + // Draw Persistent Storage struct Storage : FenceCycleDependency { vk::raii::PipelineLayout pipelineLayout; @@ -1708,7 +1722,7 @@ namespace skyline::gpu::interconnect { auto storage{std::make_shared(std::move(pipelineLayout), std::move(descriptorSet))}; // Submit Draw - executor.AddSubpass([vertexCount, firstVertex, &vkDevice = gpu.vkDevice, pipelineCreateInfo = pipelineState, storage = std::move(storage), vertexBufferHandles = std::move(vertexBufferHandles), vertexBufferOffsets = std::move(vertexBufferOffsets), pipelineCache = *pipelineCache](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &cycle, GPU &, vk::RenderPass renderPass, u32 subpassIndex) mutable { + executor.AddSubpass([=, &vkDevice = gpu.vkDevice, pipelineCreateInfo = pipelineState, storage = std::move(storage), vertexBufferHandles = std::move(vertexBufferHandles), vertexBufferOffsets = std::move(vertexBufferOffsets), pipelineCache = *pipelineCache](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr &cycle, GPU &, vk::RenderPass renderPass, u32 subpassIndex) mutable { pipelineCreateInfo.layout = *storage->pipelineLayout; pipelineCreateInfo.renderPass = renderPass; @@ -1734,7 +1748,12 @@ namespace skyline::gpu::interconnect { commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, *storage->pipelineLayout, 0, storage->descriptorSet, nullptr); - commandBuffer.draw(vertexCount, 1, firstVertex, 0); + if constexpr (IsIndexed) { + commandBuffer.bindIndexBuffer(indexBufferHandle, indexBufferOffset, indexBufferType); + commandBuffer.drawIndexed(count, 1, first, vertexOffset, 0); + } else { + commandBuffer.draw(count, 1, first, 0); + } storage->pipeline = vk::raii::Pipeline(vkDevice, pipeline.value); @@ -1743,5 +1762,13 @@ namespace skyline::gpu::interconnect { .extent = activeColorRenderTargets[0]->texture->dimensions, }, {}, activeColorRenderTargets, depthRenderTargetView); } + + void DrawVertex(u32 vertexCount, u32 firstVertex) { + Draw(vertexCount, firstVertex); + } + + void DrawIndexed(u32 indexCount, u32 firstIndex, i32 vertexOffset) { + Draw(indexCount, firstIndex, vertexOffset); + } }; } diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp index 306207a1..7ee2b29d 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp @@ -497,7 +497,11 @@ namespace skyline::soc::gm20b::engine::maxwell3d { }) MAXWELL3D_CASE(drawVertexCount, { - context.Draw(drawVertexCount, *registers.drawVertexFirst); + context.DrawVertex(drawVertexCount, *registers.drawVertexFirst); + }) + + MAXWELL3D_CASE(drawIndexCount, { + context.DrawIndexed(drawIndexCount, *registers.drawIndexFirst, *registers.drawBaseVertex); }) MAXWELL3D_STRUCT_CASE(semaphore, info, { diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h index 90031fe7..c9ba0215 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h @@ -72,8 +72,8 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x280, std::array> viewportTransforms; Register<0x300, std::array> viewports; - Register<0x35D, u32> drawVertexFirst; //!< The index of the first vertex to draw - Register<0x35E, u32> drawVertexCount; //!< The amount of vertices to draw, calling this method triggers drawing + Register<0x35D, u32> drawVertexFirst; //!< The first vertex to draw + Register<0x35E, u32> drawVertexCount; //!< The amount of vertices to draw, calling this method triggers non-indexed drawing Register<0x360, std::array> clearColorValue; Register<0x364, float> clearDepthValue; @@ -173,7 +173,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x4EC, float> lineWidthSmooth; Register<0x4ED, float> lineWidthAliased; - Register<0x50D, u32> drawBaseVertex; + Register<0x50D, i32> drawBaseVertex; Register<0x50E, u32> drawBaseInstance; Register<0x544, u32> clipDistanceEnable; @@ -224,6 +224,9 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x5F2, type::IndexBuffer> indexBuffer; + Register<0x5F7, u32> drawIndexFirst; //!< The the first element in the index buffer to draw + Register<0x5F8, u32> drawIndexCount; //!< The amount of elements to draw, calling this method triggers indexed drawing + Register<0x61F, float> depthBiasClamp; Register<0x620, std::array> isVertexInputRatePerInstance; //!< A per-VBO boolean denoting if the vertex input rate should be per vertex or per instance