Implement rasterization pipeline state

This commit is contained in:
Billy Laws 2022-09-02 15:29:18 +01:00
parent 90cd6adb91
commit 690e96bce0
5 changed files with 167 additions and 24 deletions

View File

@ -476,6 +476,72 @@ namespace skyline::gpu::interconnect::maxwell3d {
// maxwell3d::PipelineStage::TessellationEvaluation);
}
/* Rasterizer State */
void RasterizationState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
manager.Bind(handle, rasterEnable, frontPolygonMode, backPolygonMode, viewportClipControl, oglCullEnable, oglFrontFace, oglCullFace, windowOrigin, provokingVertex, polyOffset);
}
RasterizationState::RasterizationState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine) : engine{manager, dirtyHandle, engine} {}
static vk::PolygonMode ConvertPolygonMode(engine::PolygonMode mode) {
switch (mode) {
case engine::PolygonMode::Fill:
return vk::PolygonMode::eFill;
case engine::PolygonMode::Line:
return vk::PolygonMode::eLine;
case engine::PolygonMode::Point:
return vk::PolygonMode::ePoint;
}
}
static vk::CullModeFlags ConvertCullMode(engine::CullFace cullMode) {
switch (cullMode) {
case engine::CullFace::Front:
return vk::CullModeFlagBits::eFront;
case engine::CullFace::Back:
return vk::CullModeFlagBits::eBack;
case engine::CullFace::FrontAndBack:
return vk::CullModeFlagBits::eFrontAndBack;
}
}
bool ConvertDepthBiasEnable(engine::PolyOffset polyOffset, engine::PolygonMode polygonMode) {
switch (polygonMode) {
case engine::PolygonMode::Point:
return polyOffset.pointEnable;
case engine::PolygonMode::Line:
return polyOffset.lineEnable;
case engine::PolygonMode::Fill:
return polyOffset.fillEnable;
}
}
static vk::ProvokingVertexModeEXT ConvertProvokingVertex(engine::ProvokingVertex::Value provokingVertex) {
switch (provokingVertex) {
case engine::ProvokingVertex::Value::First:
return vk::ProvokingVertexModeEXT::eFirstVertex;
case engine::ProvokingVertex::Value::Last:
return vk::ProvokingVertexModeEXT::eLastVertex;
}
}
void RasterizationState::Flush() {
auto &rasterizationCreateInfo{rasterizationState.get<vk::PipelineRasterizationStateCreateInfo>()};
rasterizationCreateInfo.rasterizerDiscardEnable = !engine->rasterEnable;
rasterizationCreateInfo.polygonMode = ConvertPolygonMode(engine->frontPolygonMode);
if (engine->backPolygonMode != engine->frontPolygonMode)
Logger::Warn("Non-matching polygon modes!");
rasterizationCreateInfo.cullMode = engine->oglCullEnable ? ConvertCullMode(engine->oglCullFace) : vk::CullModeFlagBits::eNone;
// UpdateRuntimeInformation(runtimeInfo.y_negate, enabled, maxwell3d::PipelineStage::Vertex, maxwell3d::PipelineStage::Fragment);
bool origFrontFaceClockwise{engine->oglFrontFace == engine::FrontFace::CW};
rasterizationCreateInfo.frontFace = (engine->windowOrigin.flipY != origFrontFaceClockwise) ? vk::FrontFace::eClockwise : vk::FrontFace::eCounterClockwise;
rasterizationCreateInfo.depthBiasEnable = ConvertDepthBiasEnable(engine->polyOffset, engine->frontPolygonMode);
rasterizationState.get<vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT>().provokingVertexMode = ConvertProvokingVertex(engine->provokingVertex.value);
}
/* Pipeline State */
void PipelineState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
auto bindFunc{[&](auto &regs) { regs.DirtyBind(manager, handle); }};
@ -488,7 +554,8 @@ namespace skyline::gpu::interconnect::maxwell3d {
PipelineState::PipelineState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine)
: engine{manager, dirtyHandle, engine},
colorRenderTargets{util::MergeInto<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount>(manager, engine.colorRenderTargetsRegisters)},
depthRenderTarget{manager, engine.depthRenderTargetRegisters} {}
depthRenderTarget{manager, engine.depthRenderTargetRegisters},
rasterization{manager, engine.rasterizationRegisters} {}
void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) {
auto updateFunc{[&](auto &stateElem, auto &&... args) { stateElem.Update(ctx, args...); }};
@ -497,7 +564,8 @@ namespace skyline::gpu::interconnect::maxwell3d {
auto vertexState{directState.vertexInput.Build(ctx, engine->vertexInputRegisters)};
auto inputAssemblyState{directState.inputAssembly.Build()};
auto tessellationState{directState.tessellationState.Build()};
auto tessellationState{directState.tessellation.Build()};
const auto &rasterizationState{rasterization.UpdateGet().rasterizationState};
}

View File

@ -142,6 +142,34 @@ namespace skyline::gpu::interconnect::maxwell3d {
TessellationState tessellation;
};
class RasterizationState : dirty::ManualDirty {
public:
struct EngineRegisters {
const u32 &rasterEnable;
const engine::PolygonMode &frontPolygonMode;
const engine::PolygonMode &backPolygonMode;
const u32 &oglCullEnable;
const engine::CullFace &oglCullFace;
const engine::WindowOrigin &windowOrigin;
const engine::FrontFace &oglFrontFace;
const engine::ViewportClipControl &viewportClipControl;
const engine::PolyOffset &polyOffset;
const engine::ProvokingVertex &provokingVertex;
void DirtyBind(DirtyManager &manager, dirty::Handle handle) const;
};
private:
dirty::BoundSubresource<EngineRegisters> engine;
public:
vk::StructureChain<vk::PipelineRasterizationStateCreateInfo, vk::PipelineRasterizationProvokingVertexStateCreateInfoEXT> rasterizationState;
RasterizationState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine);
void Flush();
};
/**
* @brief Holds all GPU state for a pipeline, any changes to this will result in a pipeline cache lookup
*/
@ -153,6 +181,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
VertexInputState::EngineRegisters vertexInputRegisters;
InputAssemblyState::EngineRegisters inputAssemblyRegisters;
TessellationState::EngineRegisters tessellationRegisters;
RasterizationState::EngineRegisters rasterizationRegisters;
void DirtyBind(DirtyManager &manager, dirty::Handle handle) const;
};
@ -162,6 +191,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
std::array<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount> colorRenderTargets;
dirty::ManualDirtyState<DepthRenderTargetState> depthRenderTarget;
dirty::ManualDirtyState<RasterizationState> rasterization;
public:
DirectPipelineState directState;

View File

@ -351,6 +351,13 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
Fill = 0x1B02, //!< Fill the area bounded by the vertices
};
struct PolyOffset {
u32 pointEnable;
u32 lineEnable;
u32 fillEnable;
};
static_assert(sizeof(PolyOffset) == (0x3 * sizeof(u32)));
/**
* @brief A scissor which is used to reject all writes to non-masked regions
* @note All coordinates are in screen-space as defined by the viewport
@ -652,8 +659,8 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
})
enum class FrontFace : u32 {
Clockwise = 0x900,
CounterClockwise = 0x901,
CW = 0x900,
CCW = 0x901,
};
enum class CullFace : u32 {
@ -662,18 +669,48 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
FrontAndBack = 0x408,
};
union ViewVolumeClipControl {
union ViewportClipControl {
u32 raw;
enum class PixelZ : u8 {
Clip = 0,
Clamp = 1
};
enum class GuardbandScale : u8 {
Scale256,
Scale1
};
enum class GeometryClip : u8 {
WZeroClip = 0,
Passthru = 1,
FrustrumXYClip = 2,
FrustrumXYZClip = 3,
WZeroClipNoZCull = 4,
FrustrumZClip = 5,
WZeroTriFillOrClip = 6
};
enum class GuardbandZScale : u8 {
SameAsXYGuardband = 0,
Scale256 = 1,
Scale1 = 2
};
struct {
bool forceDepthRangeZeroToOne : 1;
u8 _unk0_ : 2;
bool depthClampNear : 1;
bool depthClampFar : 1;
u8 _unk1_ : 6;
bool depthClampDisable : 1;
bool minZZeroMaxZOne : 1;
GuardbandZScale guardbandZScale : 2;
PixelZ pixelMinZ : 1;
PixelZ pixelMaxZ : 1;
u8 _pad1_ : 2;
GuardbandScale geometryGuardbandScale : 1;
u8 _pad2_ : 2;
GuardbandScale linePointCullGuardbandScale : 1;
GeometryClip geometryClip : 3;
u32 _pad3_ : 18;
};
};
static_assert(sizeof(ViewVolumeClipControl) == sizeof(u32));
static_assert(sizeof(ViewportClipControl) == sizeof(u32));
union ColorWriteMask {
u32 raw;
@ -880,6 +917,15 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
};
static_assert(sizeof(SetProgramInfo) == (sizeof(u32) * 0x10));
struct ProvokingVertex {
enum class Value : u8 {
First = 0,
Last = 1,
} value : 1;
u32 _pad_ : 31;
};
static_assert(sizeof(ProvokingVertex) == sizeof(u32));
struct ZtLayer {
u16 offset;
u16 _pad_;

View File

@ -19,6 +19,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
.vertexInputRegisters = {*registers.vertexStreams, *registers.vertexStreamInstance, *registers.vertexAttributes},
.inputAssemblyRegisters = {*registers.primitiveRestartEnable},
.tessellationRegisters = {*registers.patchSize, *registers.tessellationParameters},
.rasterizationRegisters = {*registers.rasterEnable, *registers.frontPolygonMode, *registers.backPolygonMode, *registers.oglCullEnable, *registers.oglCullFace, *registers.windowOrigin, *registers.oglFrontFace, *registers.viewportClipControl, *registers.polyOffset, *registers.provokingVertex},
};
}

View File

@ -115,7 +115,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0xC8, type::TessellationParameters> tessellationParameters;
Register<0xDF, u32> rasterizerEnable;
Register<0xDF, u32> rasterEnable;
Register<0xE0, std::array<type::StreamOutBuffer, type::StreamOutBufferCount>> streamOutBuffers;
Register<0x1C0, std::array<type::TransformFeedbackBufferState, type::StreamOutBufferCount>> transformFeedbackBufferStates;
@ -127,7 +127,6 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x35B, type::ClearRect> clearRect;
Register<0x35D, u32> vertexArrayStart; //!< The first vertex to draw
struct DrawVertexArray {
@ -142,11 +141,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x364, float> zClearValue;
Register<0x368, u32> stencilClearValue;
struct PolygonMode {
type::PolygonMode front; // 0x36B
type::PolygonMode back; // 0x36C
};
Register<0x36B, PolygonMode> polygonMode;
Register<0x36B, type::PolygonMode> frontPolygonMode;
Register<0x36C, type::PolygonMode> backPolygonMode;
Register<0x370, type::PolyOffset> polyOffset;
Register<0x373, u32> patchSize;
@ -310,7 +308,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x591, u32> primitiveRestartEnable;
Register<0x592, u32> primitiveRestartIndex;
Register<0x5A1, u32> provokingVertexIsLast;
Register<0x5A1, type::ProvokingVertex> provokingVertex;
Register<0x5E7, type::ZtLayer> ztLayer;
@ -325,13 +323,13 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
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<0x646, u32> cullFaceEnable;
Register<0x647, type::FrontFace> frontFace;
Register<0x648, type::CullFace> cullFace;
Register<0x646, u32> oglCullEnable;
Register<0x647, type::FrontFace> oglFrontFace;
Register<0x648, type::CullFace> oglCullFace;
Register<0x649, u32> pixelCentreImage;
Register<0x64B, u32> viewportScaleOffsetEnable;
Register<0x64F, type::ViewVolumeClipControl> viewVolumeClipControl;
Register<0x64F, type::ViewportClipControl> viewportClipControl;
Register<0x652, type::PrimitiveTopologyControl> primitiveTopologyControl;
Register<0x65C, type::PrimitiveTopology> primitiveTopology;