Implement Maxwell3D Indexed Drawing

This commit is contained in:
PixelyIon 2021-12-24 21:34:52 +05:30
parent 23cdfe2139
commit 1c3f62b7b4
3 changed files with 41 additions and 7 deletions

View File

@ -1626,7 +1626,8 @@ namespace skyline::gpu::interconnect {
vk::raii::PipelineCache pipelineCache;
public:
void Draw(u32 vertexCount, u32 firstVertex) {
template<bool IsIndexed>
void Draw(u32 count, u32 first, i32 vertexOffset = 0) {
// Color Render Target Setup
boost::container::static_vector<std::scoped_lock<TextureView>, maxwell3d::RenderTargetCount> colorRenderTargetLocks;
boost::container::static_vector<TextureView *, maxwell3d::RenderTargetCount> 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<Storage>(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<FenceCycle> &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<FenceCycle> &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<false>(vertexCount, firstVertex);
}
void DrawIndexed(u32 indexCount, u32 firstIndex, i32 vertexOffset) {
Draw<true>(indexCount, firstIndex, vertexOffset);
}
};
}

View File

@ -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, {

View File

@ -72,8 +72,8 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x280, std::array<type::ViewportTransform, type::ViewportCount>> viewportTransforms;
Register<0x300, std::array<type::Viewport, type::ViewportCount>> 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<u32, 4>> 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<u32, type::VertexBufferCount>> isVertexInputRatePerInstance; //!< A per-VBO boolean denoting if the vertex input rate should be per vertex or per instance