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 1a311752..7ee54526 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 @@ -56,9 +56,9 @@ namespace skyline::soc::gm20b::engine::maxwell3d { } #undef REGTYPE - type::DrawTopology Maxwell3D::GetCurrentTopology() { + type::DrawTopology Maxwell3D::ApplyTopologyOverride(type::DrawTopology beginMethodTopology) { return registers.primitiveTopologyControl->override == type::PrimitiveTopologyControl::Override::UseTopologyInBeginMethods ? - registers.begin->op : type::ConvertPrimitiveTopologyToDrawTopology(*registers.primitiveTopology); + beginMethodTopology : type::ConvertPrimitiveTopologyToDrawTopology(*registers.primitiveTopology); } Maxwell3D::Maxwell3D(const DeviceState &state, ChannelContext &channelCtx, MacroState ¯oState) @@ -149,6 +149,26 @@ namespace skyline::soc::gm20b::engine::maxwell3d { return; }) + ENGINE_CASE(drawVertexArrayBeginEndInstanceSubsequent, { + deferredDraw.instanceCount++; + return; + }) + + ENGINE_CASE(drawIndexBuffer32BeginEndInstanceSubsequent, { + deferredDraw.instanceCount++; + return; + }) + + ENGINE_CASE(drawIndexBuffer16BeginEndInstanceSubsequent, { + deferredDraw.instanceCount++; + return; + }) + + ENGINE_CASE(drawIndexBuffer8BeginEndInstanceSubsequent, { + deferredDraw.instanceCount++; + return; + }) + // Once we stop calling draw methods flush the current draw since drawing is dependent on the register state not changing default: FlushDeferredDraw(); @@ -210,13 +230,99 @@ namespace skyline::soc::gm20b::engine::maxwell3d { ENGINE_STRUCT_CASE(drawVertexArray, count, { // Defer the draw until the first non-draw operation to allow for detecting instanced draws (see DeferredDrawState comment) - deferredDraw.Set(count, *registers.vertexArrayStart, 0, *registers.globalBaseInstanceIndex, GetCurrentTopology(), false); + deferredDraw.Set(count, *registers.vertexArrayStart, 0, + *registers.globalBaseInstanceIndex, + ApplyTopologyOverride(registers.begin->op), + false); batchEnableState.drawActive = true; }) + ENGINE_CASE(drawVertexArrayBeginEndInstanceFirst, { + deferredDraw.Set(drawVertexArrayBeginEndInstanceFirst.count, drawVertexArrayBeginEndInstanceFirst.startIndex, 0, + *registers.globalBaseInstanceIndex, + ApplyTopologyOverride(drawVertexArrayBeginEndInstanceFirst.topology), + false); + deferredDraw.instanceCount = 1; + batchEnableState.drawActive = true; + }) + + ENGINE_CASE(drawVertexArrayBeginEndInstanceSubsequent, { + deferredDraw.Set(drawVertexArrayBeginEndInstanceSubsequent.count, drawVertexArrayBeginEndInstanceSubsequent.startIndex, 0, + *registers.globalBaseInstanceIndex, + ApplyTopologyOverride(drawVertexArrayBeginEndInstanceSubsequent.topology), + false); + deferredDraw.instanceCount++; + batchEnableState.drawActive = true; + }) + + ENGINE_STRUCT_CASE(drawInlineIndex4X8, index0, { + throw exception("drawInlineIndex4X8 not implemented!"); + }) + + ENGINE_STRUCT_CASE(drawInlineIndex2X16, even, { + throw exception("drawInlineIndex2X16 not implemented!"); + }) + ENGINE_STRUCT_CASE(drawIndexBuffer, count, { // Defer the draw until the first non-draw operation to allow for detecting instanced draws (see DeferredDrawState comment) - deferredDraw.Set(count, registers.indexBuffer->first, *registers.globalBaseVertexIndex, *registers.globalBaseInstanceIndex, GetCurrentTopology(), true); + deferredDraw.Set(count, registers.indexBuffer->first, + *registers.globalBaseVertexIndex, *registers.globalBaseInstanceIndex, + ApplyTopologyOverride(registers.begin->op), + true); + batchEnableState.drawActive = true; + }) + + ENGINE_CASE(drawIndexBuffer32BeginEndInstanceFirst, { + deferredDraw.Set(drawIndexBuffer32BeginEndInstanceFirst.count, drawIndexBuffer32BeginEndInstanceFirst.first, + *registers.globalBaseVertexIndex, *registers.globalBaseInstanceIndex, + ApplyTopologyOverride(drawIndexBuffer32BeginEndInstanceFirst.topology), + true); + deferredDraw.instanceCount = 1; + batchEnableState.drawActive = true; + }) + + ENGINE_CASE(drawIndexBuffer16BeginEndInstanceFirst, { + deferredDraw.Set(drawIndexBuffer16BeginEndInstanceFirst.count, drawIndexBuffer16BeginEndInstanceFirst.first, + *registers.globalBaseVertexIndex, *registers.globalBaseInstanceIndex, + ApplyTopologyOverride(drawIndexBuffer16BeginEndInstanceFirst.topology), + true); + deferredDraw.instanceCount = 1; + batchEnableState.drawActive = true; + }) + + ENGINE_CASE(drawIndexBuffer8BeginEndInstanceFirst, { + deferredDraw.Set(drawIndexBuffer8BeginEndInstanceFirst.count, drawIndexBuffer8BeginEndInstanceFirst.first, + *registers.globalBaseVertexIndex, *registers.globalBaseInstanceIndex, + ApplyTopologyOverride(drawIndexBuffer8BeginEndInstanceFirst.topology), + true); + deferredDraw.instanceCount = 1; + batchEnableState.drawActive = true; + }) + + ENGINE_CASE(drawIndexBuffer32BeginEndInstanceSubsequent, { + deferredDraw.Set(drawIndexBuffer32BeginEndInstanceSubsequent.count, drawIndexBuffer32BeginEndInstanceSubsequent.first, + *registers.globalBaseVertexIndex, *registers.globalBaseInstanceIndex, + ApplyTopologyOverride(drawIndexBuffer32BeginEndInstanceSubsequent.topology), + true); + deferredDraw.instanceCount++; + batchEnableState.drawActive = true; + }) + + ENGINE_CASE(drawIndexBuffer16BeginEndInstanceSubsequent, { + deferredDraw.Set(drawIndexBuffer16BeginEndInstanceSubsequent.count, drawIndexBuffer16BeginEndInstanceSubsequent.first, + *registers.globalBaseVertexIndex, *registers.globalBaseInstanceIndex, + ApplyTopologyOverride(drawIndexBuffer16BeginEndInstanceSubsequent.topology), + true); + deferredDraw.instanceCount++; + batchEnableState.drawActive = true; + }) + + ENGINE_CASE(drawIndexBuffer8BeginEndInstanceSubsequent, { + deferredDraw.Set(drawIndexBuffer8BeginEndInstanceSubsequent.count, drawIndexBuffer8BeginEndInstanceSubsequent.first, + *registers.globalBaseVertexIndex, *registers.globalBaseInstanceIndex, + ApplyTopologyOverride(drawIndexBuffer8BeginEndInstanceSubsequent.topology), + true); + deferredDraw.instanceCount++; batchEnableState.drawActive = true; }) 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 cd7a9ed8..707f1a1e 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 @@ -70,7 +70,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { } } deferredDraw{}; - type::DrawTopology GetCurrentTopology(); + type::DrawTopology ApplyTopologyOverride(type::DrawTopology beginMethodTopology); void FlushDeferredDraw(); @@ -114,6 +114,11 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0xB2, type::SyncpointAction> syncpointAction; + struct DrawZeroIndex { + u32 count; + }; + Register<0xC1, DrawZeroIndex> drawZeroIndex; + Register<0xC8, type::TessellationParameters> tessellationParameters; Register<0xDF, u32> rasterEnable; @@ -184,6 +189,18 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x458, std::array> vertexAttributes; + Register<0x484, u32> invalidateSamplerCacheAll; + Register<0x485, u32> invalidateTextureHeaderCacheAll; + + struct DrawVertexArrayBeginEndInstance { + u16 startIndex; + u16 count : 12; + type::DrawTopology topology : 4; + }; + + Register<0x485, DrawVertexArrayBeginEndInstance> drawVertexArrayBeginEndInstanceFirst; + Register<0x486, DrawVertexArrayBeginEndInstance> drawVertexArrayBeginEndInstanceSubsequent; + Register<0x487, type::CtSelect> ctSelect; Register<0x48A, type::ZtSize> ztSize; @@ -196,9 +213,25 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x4B9, u32> blendStatePerTargetEnable; Register<0x4BA, u32> depthWriteEnable; Register<0x4BB, u32> alphaTestEnable; + + struct InlineIndexAlign { + u32 count : 30; + u8 start : 2; + }; + + struct DrawInlineIndex { + u8 index0; + u8 index1; + u8 index2; + u8 index3; + }; + + Register<0x4C1, DrawInlineIndex> drawInlineIndex4X8; + Register<0x4C3, type::CompareFunc> depthFunc; Register<0x4C4, float> alphaRef; Register<0x4C5, type::CompareFunc> alphaFunc; + Register<0x4C6, u32> drawAutoStride; struct BlendConstant { @@ -247,7 +280,24 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x56F, float> depthBias; + Register<0x57A, u32> drawInlineIndex; + + struct InlineIndex2X16Align { + u32 count : 31; + bool startOdd : 1; + }; + + Register<0x57B, InlineIndex2X16Align> inlineIndex2X16Align; + + struct DrawInlineIndex2X16 { + u16 even; + u16 odd; + }; + + Register<0x57C, DrawInlineIndex2X16> drawInlineIndex2X16; + Register<0x581, type::PointCoordReplace> pointCoordReplace; + Register<0x582, Address> programRegion; Register<0x585, u32> end; //!< Method-only register with no real value, used after calling vertexBeginGl to invoke the draw @@ -299,6 +349,19 @@ namespace skyline::soc::gm20b::engine::maxwell3d { }; Register<0x5F8, DrawIndexBuffer> drawIndexBuffer; + struct DrawIndexBufferBeginEndInstance { + u16 first; + u16 count : 12; + type::DrawTopology topology : 4; + }; + + Register<0x5F9, DrawIndexBufferBeginEndInstance> drawIndexBuffer32BeginEndInstanceFirst; + Register<0x5FA, DrawIndexBufferBeginEndInstance> drawIndexBuffer16BeginEndInstanceFirst; + Register<0x5FB, DrawIndexBufferBeginEndInstance> drawIndexBuffer8BeginEndInstanceFirst; + Register<0x5FC, DrawIndexBufferBeginEndInstance> drawIndexBuffer32BeginEndInstanceSubsequent; + Register<0x5FD, DrawIndexBufferBeginEndInstance> drawIndexBuffer16BeginEndInstanceSubsequent; + Register<0x5FE, DrawIndexBufferBeginEndInstance> drawIndexBuffer8BeginEndInstanceSubsequent; + Register<0x61F, float> depthBiasClamp; Register<0x620, std::array> vertexStreamInstance; //!< A per-VBO boolean denoting if the vertex input rate should be per vertex or per instance