Implement Maxwell3D Rasterizer State

Maxwell3D registers relevant to the Vulkan Rasterizer state have been implemented aside from certain features such as per-face polygon modes that cannot be implemented due to Vulkan limitations. A quirk was utilized to dynamically support the provoking vertex being the last vertex as opposed to the first as well.
This commit is contained in:
PixelyIon 2021-11-12 01:41:04 +05:30
parent 8ef225a37d
commit 5ed26fef23
4 changed files with 208 additions and 2 deletions

View File

@ -26,6 +26,8 @@ namespace skyline::gpu::interconnect {
public:
GraphicsContext(GPU &gpu, soc::gm20b::ChannelContext &channelCtx, gpu::interconnect::CommandExecutor &executor) : gpu(gpu), channelCtx(channelCtx), executor(executor) {
scissors.fill(DefaultScissor);
if (!gpu.quirks.supportsLastProvokingVertex)
rasterizerState.unlink<vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT>();
}
/* Render Targets + Render Target Control */
@ -368,5 +370,110 @@ namespace skyline::gpu::interconnect {
shader.offset = offset;
shader.data = span<u8>{};
}
/* Rasterizer State */
private:
vk::StructureChain<vk::PipelineRasterizationStateCreateInfo, vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT> rasterizerState;
bool cullFaceEnabled{};
vk::CullModeFlags cullMode{}; //!< The current cull mode regardless of it being enabled or disabled
vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT provokingVertexState{};
bool depthBiasPoint{}, depthBiasLine{}, depthBiasFill{};
public:
void SetDepthClampEnabled(bool enabled) {
rasterizerState.get<vk::PipelineRasterizationStateCreateInfo>().depthClampEnable = enabled;
}
vk::PolygonMode ConvertPolygonMode(maxwell3d::PolygonMode mode) {
switch (mode) {
case maxwell3d::PolygonMode::Point:
return vk::PolygonMode::ePoint;
case maxwell3d::PolygonMode::Line:
return vk::PolygonMode::eLine;
case maxwell3d::PolygonMode::Fill:
return vk::PolygonMode::eFill;
}
}
void SetPolygonModeFront(maxwell3d::PolygonMode mode) {
rasterizerState.get<vk::PipelineRasterizationStateCreateInfo>().polygonMode = ConvertPolygonMode(mode);
}
void SetPolygonModeBack(maxwell3d::PolygonMode mode) {
auto frontPolygonMode{rasterizerState.get<vk::PipelineRasterizationStateCreateInfo>().polygonMode};
auto backPolygonMode{ConvertPolygonMode(mode)};
if (frontPolygonMode != backPolygonMode)
Logger::Warn("Cannot set back-facing polygon mode ({}) different from front-facing polygon mode ({}) due to Vulkan constraints", vk::to_string(backPolygonMode), vk::to_string(frontPolygonMode));
}
void SetCullFaceEnabled(bool enabled) {
cullFaceEnabled = enabled;
if (!enabled)
rasterizerState.get<vk::PipelineRasterizationStateCreateInfo>().cullMode = {};
}
void SetFrontFace(maxwell3d::FrontFace face) {
rasterizerState.get<vk::PipelineRasterizationStateCreateInfo>().frontFace = [face]() {
switch (face) {
case maxwell3d::FrontFace::Clockwise:
return vk::FrontFace::eClockwise;
case maxwell3d::FrontFace::CounterClockwise:
return vk::FrontFace::eCounterClockwise;
}
}();
}
void SetCullFace(maxwell3d::CullFace face) {
cullMode = [face]() -> vk::CullModeFlags {
switch (face) {
case maxwell3d::CullFace::Front:
return vk::CullModeFlagBits::eFront;
case maxwell3d::CullFace::Back:
return vk::CullModeFlagBits::eBack;
case maxwell3d::CullFace::FrontAndBack:
return vk::CullModeFlagBits::eFrontAndBack;
}
}();
if (cullFaceEnabled)
rasterizerState.get<vk::PipelineRasterizationStateCreateInfo>().cullMode = cullMode;
}
void SetProvokingVertex(bool isLast) {
if (isLast) {
if (!gpu.quirks.supportsLastProvokingVertex)
Logger::Warn("Cannot set provoking vertex to last without host GPU support");
rasterizerState.get<vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT>().provokingVertexMode = vk::ProvokingVertexModeEXT::eLastVertex;
} else {
rasterizerState.get<vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT>().provokingVertexMode = vk::ProvokingVertexModeEXT::eFirstVertex;
}
}
void SetLineWidth(float width) {
rasterizerState.get<vk::PipelineRasterizationStateCreateInfo>().lineWidth = width;
}
void SetDepthBiasPointEnabled(bool enabled) {
depthBiasPoint = enabled;
}
void SetDepthBiasLineEnabled(bool enabled) {
depthBiasLine = enabled;
}
void SetDepthBiasFillEnabled(bool enabled) {
depthBiasFill = enabled;
}
void SetDepthBiasConstantFactor(float factor) {
rasterizerState.get<vk::PipelineRasterizationStateCreateInfo>().depthBiasConstantFactor = factor;
}
void SetDepthBiasClamp(float clamp) {
rasterizerState.get<vk::PipelineRasterizationStateCreateInfo>().depthBiasClamp = clamp;
}
void SetDepthBiasSlopeFactor(float factor) {
rasterizerState.get<vk::PipelineRasterizationStateCreateInfo>().depthBiasSlopeFactor = factor;
}
};
}

View File

@ -412,6 +412,19 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
FrontAndBack = 0x408,
};
union ViewVolumeClipControl {
u32 raw;
struct {
bool forceDepthRangeZeroToOne : 1;
u8 _unk0_ : 2;
bool depthClampNear : 1;
bool depthClampFar : 1;
u8 _unk1_ : 7;
bool depthClampDisable : 1;
};
};
static_assert(sizeof(ViewVolumeClipControl) == sizeof(u32));
union ColorWriteMask {
u32 raw;

View File

@ -208,6 +208,22 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
static_assert(4 < BOOST_PP_LIMIT_REPEAT);
#undef COLOR_CLEAR_CALLBACKS
MAXWELL3D_STRUCT_CASE(polygonMode, front, {
context.SetPolygonModeFront(front);
})
MAXWELL3D_STRUCT_CASE(depthBiasEnable, point, {
context.SetDepthBiasPointEnabled(point);
})
MAXWELL3D_STRUCT_CASE(depthBiasEnable, line, {
context.SetDepthBiasLineEnabled(line);
})
MAXWELL3D_STRUCT_CASE(depthBiasEnable, fill, {
context.SetDepthBiasFillEnabled(fill);
})
#define SCISSOR_CALLBACKS(z, index, data) \
MAXWELL3D_ARRAY_STRUCT_CASE(scissors, index, enable, { \
context.SetScissor(index, enable ? registers.scissors[index] : std::optional<type::Scissor>{}); \
@ -226,6 +242,61 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
MAXWELL3D_CASE(renderTargetControl, {
context.UpdateRenderTargetControl(renderTargetControl);
})
MAXWELL3D_CASE(lineWidthSmooth, {
if (*registers.lineSmoothEnable)
context.SetLineWidth(lineWidthSmooth);
})
MAXWELL3D_CASE(lineWidthAliased, {
if (!*registers.lineSmoothEnable)
context.SetLineWidth(lineWidthAliased);
})
MAXWELL3D_CASE(depthBiasFactor, {
context.SetDepthBiasSlopeFactor(depthBiasFactor);
})
MAXWELL3D_CASE(lineSmoothEnable, {
context.SetLineWidth(lineSmoothEnable ? *registers.lineWidthSmooth : *registers.lineWidthAliased);
})
MAXWELL3D_CASE(depthBiasUnits, {
context.SetDepthBiasConstantFactor(depthBiasUnits / 2.0f);
})
MAXWELL3D_STRUCT_CASE(setProgramRegion, high, {
context.SetShaderBaseIovaHigh(high);
})
MAXWELL3D_STRUCT_CASE(setProgramRegion, low, {
context.SetShaderBaseIovaLow(low);
})
MAXWELL3D_CASE(provokingVertexIsLast, {
context.SetProvokingVertex(provokingVertexIsLast);
})
MAXWELL3D_CASE(depthBiasClamp, {
context.SetDepthBiasClamp(depthBiasClamp);
})
MAXWELL3D_CASE(cullFaceEnable, {
context.SetCullFaceEnabled(cullFaceEnable);
})
MAXWELL3D_CASE(frontFace, {
context.SetFrontFace(frontFace);
})
MAXWELL3D_CASE(cullFace, {
context.SetCullFace(cullFace);
})
MAXWELL3D_CASE(viewVolumeClipControl, {
context.SetDepthClampEnabled(!viewVolumeClipControl.depthClampDisable);
})
#define SET_SHADER_ENABLE_CALLBACK(z, index, data) \
MAXWELL3D_ARRAY_STRUCT_CASE(setProgram, index, info, { \
context.SetShaderEnabled(info.stage, info.enable); \

View File

@ -79,6 +79,13 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x380, std::array<type::Scissor, type::ViewportCount>> scissors;
struct DepthBiasEnable {
u32 point; // 0x370
u32 line; // 0x371
u32 fill; // 0x372
};
Register<0x370, DepthBiasEnable> depthBiasEnable;
struct StencilBackExtra {
u32 compareRef; // 0x3D5
u32 writeMask; // 0x3D6
@ -162,7 +169,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
};
Register<0x557, SamplerPool> samplerPool;
Register<0x55B, u32> polygonOffsetFactor;
Register<0x55B, float> depthBiasFactor;
Register<0x55C, u32> lineSmoothEnable;
struct TexturePool {
@ -171,7 +178,6 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
};
Register<0x55D, TexturePool> texturePool;
Register<0x565, u32> stencilTwoSideEnable;
struct StencilBack {
@ -182,16 +188,25 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
};
Register<0x566, StencilBack> stencilBack;
Register<0x56F, float> depthBiasUnits;
Register<0x581, type::PointCoordReplace> pointCoordReplace;
Register<0x582, type::Address> setProgramRegion;
Register<0x5A1, u32> provokingVertexIsLast;
Register<0x646, u32> cullFaceEnable;
Register<0x647, type::FrontFace> frontFace;
Register<0x648, type::CullFace> cullFace;
Register<0x649, u32> pixelCentreImage;
Register<0x64B, u32> viewportTransformEnable;
Register<0x674, type::ClearBuffers> clearBuffers;
Register<0x680, std::array<type::ColorWriteMask, type::RenderTargetCount>> colorMask;
Register<0x61F, float> depthBiasClamp;
Register<0x64F, type::ViewVolumeClipControl> viewVolumeClipControl;
struct Semaphore {
type::Address address; // 0x6C0
u32 payload; // 0x6C2