Implement the draw(...)BeginEnd Maxwell3D draw registers

Used by guest Vulkan games and nouveau.
This commit is contained in:
Billy Laws 2022-10-30 16:38:22 +00:00
parent 270ef3e0d2
commit c50852e546
2 changed files with 174 additions and 5 deletions

View File

@ -56,9 +56,9 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
} }
#undef REGTYPE #undef REGTYPE
type::DrawTopology Maxwell3D::GetCurrentTopology() { type::DrawTopology Maxwell3D::ApplyTopologyOverride(type::DrawTopology beginMethodTopology) {
return registers.primitiveTopologyControl->override == type::PrimitiveTopologyControl::Override::UseTopologyInBeginMethods ? 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 &macroState) Maxwell3D::Maxwell3D(const DeviceState &state, ChannelContext &channelCtx, MacroState &macroState)
@ -149,6 +149,26 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
return; 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 // Once we stop calling draw methods flush the current draw since drawing is dependent on the register state not changing
default: default:
FlushDeferredDraw(); FlushDeferredDraw();
@ -210,13 +230,99 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
ENGINE_STRUCT_CASE(drawVertexArray, count, { ENGINE_STRUCT_CASE(drawVertexArray, count, {
// Defer the draw until the first non-draw operation to allow for detecting instanced draws (see DeferredDrawState comment) // 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; 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, { ENGINE_STRUCT_CASE(drawIndexBuffer, count, {
// Defer the draw until the first non-draw operation to allow for detecting instanced draws (see DeferredDrawState comment) // 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; batchEnableState.drawActive = true;
}) })

View File

@ -70,7 +70,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
} }
} deferredDraw{}; } deferredDraw{};
type::DrawTopology GetCurrentTopology(); type::DrawTopology ApplyTopologyOverride(type::DrawTopology beginMethodTopology);
void FlushDeferredDraw(); void FlushDeferredDraw();
@ -114,6 +114,11 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0xB2, type::SyncpointAction> syncpointAction; Register<0xB2, type::SyncpointAction> syncpointAction;
struct DrawZeroIndex {
u32 count;
};
Register<0xC1, DrawZeroIndex> drawZeroIndex;
Register<0xC8, type::TessellationParameters> tessellationParameters; Register<0xC8, type::TessellationParameters> tessellationParameters;
Register<0xDF, u32> rasterEnable; Register<0xDF, u32> rasterEnable;
@ -184,6 +189,18 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x458, std::array<type::VertexAttribute, type::VertexAttributeCount>> vertexAttributes; Register<0x458, std::array<type::VertexAttribute, type::VertexAttributeCount>> 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<0x487, type::CtSelect> ctSelect;
Register<0x48A, type::ZtSize> ztSize; Register<0x48A, type::ZtSize> ztSize;
@ -196,9 +213,25 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x4B9, u32> blendStatePerTargetEnable; Register<0x4B9, u32> blendStatePerTargetEnable;
Register<0x4BA, u32> depthWriteEnable; Register<0x4BA, u32> depthWriteEnable;
Register<0x4BB, u32> alphaTestEnable; 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<0x4C3, type::CompareFunc> depthFunc;
Register<0x4C4, float> alphaRef; Register<0x4C4, float> alphaRef;
Register<0x4C5, type::CompareFunc> alphaFunc; Register<0x4C5, type::CompareFunc> alphaFunc;
Register<0x4C6, u32> drawAutoStride; Register<0x4C6, u32> drawAutoStride;
struct BlendConstant { struct BlendConstant {
@ -247,7 +280,24 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x56F, float> depthBias; 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<0x581, type::PointCoordReplace> pointCoordReplace;
Register<0x582, Address> programRegion; Register<0x582, Address> programRegion;
Register<0x585, u32> end; //!< Method-only register with no real value, used after calling vertexBeginGl to invoke the draw 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; 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<0x61F, float> depthBiasClamp;
Register<0x620, std::array<type::VertexStreamInstance, type::VertexStreamCount>> vertexStreamInstance; //!< A per-VBO boolean denoting if the vertex input rate should be per vertex or per instance Register<0x620, std::array<type::VertexStreamInstance, type::VertexStreamCount>> vertexStreamInstance; //!< A per-VBO boolean denoting if the vertex input rate should be per vertex or per instance