mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-25 23:54:15 +01:00
Implement Maxwell3D Tessellation State
This implements all Maxwell3D registers and HLE Vulkan state for Tessellation including invalidation of the TCS (Tessellation Control Shader) state during state changes.
This commit is contained in:
parent
de796cd2cd
commit
f9c052d1b7
@ -1868,6 +1868,86 @@ namespace skyline::gpu::interconnect {
|
||||
inputAssemblyState.primitiveRestartEnable = enable;
|
||||
}
|
||||
|
||||
/* Tessellation */
|
||||
private:
|
||||
vk::PipelineTessellationStateCreateInfo tessellationState{};
|
||||
maxwell3d::TessellationPrimitive tessellationPrimitive{};
|
||||
maxwell3d::TessellationSpacing tessellationSpacing{};
|
||||
bool isTessellationWindingClockwise{};
|
||||
|
||||
bool IsTessellationModeClockwise(maxwell3d::TessellationPrimitive primitive, maxwell3d::TessellationWinding winding) {
|
||||
if (primitive == maxwell3d::TessellationPrimitive::Isoline)
|
||||
return false;
|
||||
|
||||
switch (winding) {
|
||||
case maxwell3d::TessellationWinding::CounterClockwiseAndNotConnected:
|
||||
case maxwell3d::TessellationWinding::ConnectedTriangle:
|
||||
return false;
|
||||
|
||||
case maxwell3d::TessellationWinding::ClockwiseTriangle:
|
||||
case maxwell3d::TessellationWinding::ClockwiseConnectedTriangle:
|
||||
return true;
|
||||
|
||||
default:
|
||||
throw exception("Unimplemented Maxwell3D Tessellation Winding: {}", winding);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void SetTessellationPatchSize(u32 patchControlPoints) {
|
||||
tessellationState.patchControlPoints = patchControlPoints;
|
||||
}
|
||||
|
||||
void SetTessellationMode(maxwell3d::TessellationPrimitive primitive, maxwell3d::TessellationSpacing spacing, maxwell3d::TessellationWinding winding) {
|
||||
if (tessellationPrimitive != primitive) {
|
||||
auto shaderPrimitive{[](maxwell3d::TessellationPrimitive primitive) -> ShaderCompiler::TessPrimitive {
|
||||
using Primitive = maxwell3d::TessellationPrimitive;
|
||||
using ShaderPrimitive = ShaderCompiler::TessPrimitive;
|
||||
switch (primitive) {
|
||||
case Primitive::Isoline:
|
||||
return ShaderPrimitive::Isolines;
|
||||
case Primitive::Triangle:
|
||||
return ShaderPrimitive::Triangles;
|
||||
case Primitive::Quad:
|
||||
return ShaderPrimitive::Quads;
|
||||
|
||||
default:
|
||||
throw exception("Unimplemented Maxwell3D Tessellation Primitive: {}", primitive);
|
||||
}
|
||||
}(primitive)};
|
||||
|
||||
UpdateRuntimeInformation(runtimeInfo.tess_primitive, shaderPrimitive, maxwell3d::PipelineStage::TessellationEvaluation);
|
||||
tessellationPrimitive = primitive;
|
||||
}
|
||||
|
||||
if (tessellationSpacing != spacing) {
|
||||
auto shaderTessellationSpacing{[](maxwell3d::TessellationSpacing spacing) -> ShaderCompiler::TessSpacing {
|
||||
using Spacing = maxwell3d::TessellationSpacing;
|
||||
using ShaderSpacing = ShaderCompiler::TessSpacing;
|
||||
switch (spacing) {
|
||||
case Spacing::Equal:
|
||||
return ShaderSpacing::Equal;
|
||||
case Spacing::FractionalEven:
|
||||
return ShaderSpacing::FractionalEven;
|
||||
case Spacing::FractionalOdd:
|
||||
return ShaderSpacing::FractionalOdd;
|
||||
|
||||
default:
|
||||
throw exception("Unimplemented Maxwell3D Tessellation Spacing: {}", spacing);
|
||||
}
|
||||
}(spacing)};
|
||||
|
||||
UpdateRuntimeInformation(runtimeInfo.tess_spacing, shaderTessellationSpacing, maxwell3d::PipelineStage::TessellationEvaluation);
|
||||
tessellationSpacing = spacing;
|
||||
}
|
||||
|
||||
bool isClockwise{IsTessellationModeClockwise(primitive, winding)};
|
||||
if (isTessellationWindingClockwise != isClockwise) {
|
||||
UpdateRuntimeInformation(runtimeInfo.tess_clockwise, isClockwise, maxwell3d::PipelineStage::TessellationEvaluation);
|
||||
isTessellationWindingClockwise = isClockwise;
|
||||
}
|
||||
}
|
||||
|
||||
/* Index Buffer */
|
||||
private:
|
||||
struct IndexBuffer {
|
||||
@ -2798,6 +2878,7 @@ namespace skyline::gpu::interconnect {
|
||||
.stageCount = static_cast<u32>(shaderStages.size()),
|
||||
.pVertexInputState = &vertexState.get<vk::PipelineVertexInputStateCreateInfo>(),
|
||||
.pInputAssemblyState = &inputAssemblyState,
|
||||
.pTessellationState = &tessellationState,
|
||||
.pViewportState = &viewportState,
|
||||
.pRasterizationState = &rasterizerState.get<vk::PipelineRasterizationStateCreateInfo>(),
|
||||
.pMultisampleState = &multisampleState,
|
||||
|
@ -27,6 +27,35 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
|
||||
};
|
||||
static_assert(sizeof(SyncpointAction) == sizeof(u32));
|
||||
|
||||
/**
|
||||
* @brief The input primitive for a tessellated surface
|
||||
*/
|
||||
enum class TessellationPrimitive : u8 {
|
||||
Isoline = 0,
|
||||
Triangle = 1,
|
||||
Quad = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The spacing between tessellated vertices during primitive generation
|
||||
*/
|
||||
enum class TessellationSpacing : u8 {
|
||||
Equal = 0,
|
||||
FractionalOdd = 1,
|
||||
FractionalEven = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The winding order and connectivity of tessellated primitives during primitive generation
|
||||
*/
|
||||
enum class TessellationWinding : u8 {
|
||||
CounterClockwiseAndNotConnected = 0, //!< Counter-clockwise, not connected
|
||||
ConnectedIsoline = 1, //!< Counter-clockwise, connected (Only for Isolines)
|
||||
ClockwiseTriangle = 1, //<! Clockwise, not connected (Only for Triangles)
|
||||
ConnectedTriangle = 2, //!< Counter-clockwise, connected (Only for Triangles)
|
||||
ClockwiseConnectedTriangle = 3, //!< Clockwise, connected (Only for Triangles)
|
||||
};
|
||||
|
||||
constexpr static size_t RenderTargetCount{8}; //!< Maximum amount of render targets that can be bound at once on Maxwell 3D
|
||||
|
||||
struct RenderTargetTileMode {
|
||||
|
@ -177,6 +177,14 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
context.SetPolygonModeFront(front);
|
||||
})
|
||||
|
||||
ENGINE_CASE(tessellationPatchSize, {
|
||||
context.SetTessellationPatchSize(tessellationPatchSize);
|
||||
})
|
||||
|
||||
ENGINE_CASE(tessellationMode, {
|
||||
context.SetTessellationMode(tessellationMode.primitive, tessellationMode.spacing, tessellationMode.winding);
|
||||
})
|
||||
|
||||
ENGINE_STRUCT_CASE(depthBiasEnable, point, {
|
||||
context.SetDepthBiasPointEnabled(point);
|
||||
})
|
||||
|
@ -74,6 +74,18 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
|
||||
Register<0xB2, type::SyncpointAction> syncpointAction;
|
||||
|
||||
union TessellationMode {
|
||||
struct {
|
||||
type::TessellationPrimitive primitive : 2;
|
||||
u8 _pad0_ : 2;
|
||||
type::TessellationSpacing spacing : 2;
|
||||
u8 _pad1_ : 2;
|
||||
type::TessellationWinding winding : 2;
|
||||
};
|
||||
u32 raw;
|
||||
};
|
||||
Register<0xC8, TessellationMode> tessellationMode;
|
||||
|
||||
Register<0xDF, u32> rasterizerEnable;
|
||||
Register<0x200, std::array<type::ColorRenderTarget, type::RenderTargetCount>> renderTargets;
|
||||
Register<0x280, std::array<type::ViewportTransform, type::ViewportCount>> viewportTransforms;
|
||||
@ -94,6 +106,8 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
||||
};
|
||||
Register<0x36B, PolygonMode> polygonMode;
|
||||
|
||||
Register<0x373, u32> tessellationPatchSize;
|
||||
|
||||
Register<0x380, std::array<type::Scissor, type::ViewportCount>> scissors;
|
||||
|
||||
struct DepthBiasEnable {
|
||||
|
Loading…
Reference in New Issue
Block a user