mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-23 11:59:15 +01:00
Implement rasterization pipeline state
This commit is contained in:
parent
90cd6adb91
commit
690e96bce0
@ -476,6 +476,72 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
// maxwell3d::PipelineStage::TessellationEvaluation);
|
// 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 */
|
/* Pipeline State */
|
||||||
void PipelineState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
|
void PipelineState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
|
||||||
auto bindFunc{[&](auto ®s) { regs.DirtyBind(manager, handle); }};
|
auto bindFunc{[&](auto ®s) { regs.DirtyBind(manager, handle); }};
|
||||||
@ -488,7 +554,8 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
PipelineState::PipelineState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine)
|
PipelineState::PipelineState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine)
|
||||||
: engine{manager, dirtyHandle, engine},
|
: engine{manager, dirtyHandle, engine},
|
||||||
colorRenderTargets{util::MergeInto<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount>(manager, engine.colorRenderTargetsRegisters)},
|
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) {
|
void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) {
|
||||||
auto updateFunc{[&](auto &stateElem, auto &&... args) { stateElem.Update(ctx, args...); }};
|
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 vertexState{directState.vertexInput.Build(ctx, engine->vertexInputRegisters)};
|
||||||
auto inputAssemblyState{directState.inputAssembly.Build()};
|
auto inputAssemblyState{directState.inputAssembly.Build()};
|
||||||
auto tessellationState{directState.tessellationState.Build()};
|
auto tessellationState{directState.tessellation.Build()};
|
||||||
|
const auto &rasterizationState{rasterization.UpdateGet().rasterizationState};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +142,34 @@ namespace skyline::gpu::interconnect::maxwell3d {
|
|||||||
TessellationState tessellation;
|
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
|
* @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;
|
VertexInputState::EngineRegisters vertexInputRegisters;
|
||||||
InputAssemblyState::EngineRegisters inputAssemblyRegisters;
|
InputAssemblyState::EngineRegisters inputAssemblyRegisters;
|
||||||
TessellationState::EngineRegisters tessellationRegisters;
|
TessellationState::EngineRegisters tessellationRegisters;
|
||||||
|
RasterizationState::EngineRegisters rasterizationRegisters;
|
||||||
|
|
||||||
void DirtyBind(DirtyManager &manager, dirty::Handle handle) const;
|
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;
|
std::array<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount> colorRenderTargets;
|
||||||
dirty::ManualDirtyState<DepthRenderTargetState> depthRenderTarget;
|
dirty::ManualDirtyState<DepthRenderTargetState> depthRenderTarget;
|
||||||
|
dirty::ManualDirtyState<RasterizationState> rasterization;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DirectPipelineState directState;
|
DirectPipelineState directState;
|
||||||
|
@ -351,6 +351,13 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
|
|||||||
Fill = 0x1B02, //!< Fill the area bounded by the vertices
|
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
|
* @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
|
* @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 {
|
enum class FrontFace : u32 {
|
||||||
Clockwise = 0x900,
|
CW = 0x900,
|
||||||
CounterClockwise = 0x901,
|
CCW = 0x901,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class CullFace : u32 {
|
enum class CullFace : u32 {
|
||||||
@ -662,18 +669,48 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
|
|||||||
FrontAndBack = 0x408,
|
FrontAndBack = 0x408,
|
||||||
};
|
};
|
||||||
|
|
||||||
union ViewVolumeClipControl {
|
union ViewportClipControl {
|
||||||
u32 raw;
|
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 {
|
struct {
|
||||||
bool forceDepthRangeZeroToOne : 1;
|
bool minZZeroMaxZOne : 1;
|
||||||
u8 _unk0_ : 2;
|
GuardbandZScale guardbandZScale : 2;
|
||||||
bool depthClampNear : 1;
|
PixelZ pixelMinZ : 1;
|
||||||
bool depthClampFar : 1;
|
PixelZ pixelMaxZ : 1;
|
||||||
u8 _unk1_ : 6;
|
u8 _pad1_ : 2;
|
||||||
bool depthClampDisable : 1;
|
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 {
|
union ColorWriteMask {
|
||||||
u32 raw;
|
u32 raw;
|
||||||
@ -880,6 +917,15 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(SetProgramInfo) == (sizeof(u32) * 0x10));
|
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 {
|
struct ZtLayer {
|
||||||
u16 offset;
|
u16 offset;
|
||||||
u16 _pad_;
|
u16 _pad_;
|
||||||
|
@ -19,6 +19,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
.vertexInputRegisters = {*registers.vertexStreams, *registers.vertexStreamInstance, *registers.vertexAttributes},
|
.vertexInputRegisters = {*registers.vertexStreams, *registers.vertexStreamInstance, *registers.vertexAttributes},
|
||||||
.inputAssemblyRegisters = {*registers.primitiveRestartEnable},
|
.inputAssemblyRegisters = {*registers.primitiveRestartEnable},
|
||||||
.tessellationRegisters = {*registers.patchSize, *registers.tessellationParameters},
|
.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},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
|
|
||||||
Register<0xC8, type::TessellationParameters> tessellationParameters;
|
Register<0xC8, type::TessellationParameters> tessellationParameters;
|
||||||
|
|
||||||
Register<0xDF, u32> rasterizerEnable;
|
Register<0xDF, u32> rasterEnable;
|
||||||
|
|
||||||
Register<0xE0, std::array<type::StreamOutBuffer, type::StreamOutBufferCount>> streamOutBuffers;
|
Register<0xE0, std::array<type::StreamOutBuffer, type::StreamOutBufferCount>> streamOutBuffers;
|
||||||
Register<0x1C0, std::array<type::TransformFeedbackBufferState, type::StreamOutBufferCount>> transformFeedbackBufferStates;
|
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<0x35B, type::ClearRect> clearRect;
|
||||||
|
|
||||||
|
|
||||||
Register<0x35D, u32> vertexArrayStart; //!< The first vertex to draw
|
Register<0x35D, u32> vertexArrayStart; //!< The first vertex to draw
|
||||||
|
|
||||||
struct DrawVertexArray {
|
struct DrawVertexArray {
|
||||||
@ -142,11 +141,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
Register<0x364, float> zClearValue;
|
Register<0x364, float> zClearValue;
|
||||||
Register<0x368, u32> stencilClearValue;
|
Register<0x368, u32> stencilClearValue;
|
||||||
|
|
||||||
struct PolygonMode {
|
Register<0x36B, type::PolygonMode> frontPolygonMode;
|
||||||
type::PolygonMode front; // 0x36B
|
Register<0x36C, type::PolygonMode> backPolygonMode;
|
||||||
type::PolygonMode back; // 0x36C
|
|
||||||
};
|
Register<0x370, type::PolyOffset> polyOffset;
|
||||||
Register<0x36B, PolygonMode> polygonMode;
|
|
||||||
|
|
||||||
Register<0x373, u32> patchSize;
|
Register<0x373, u32> patchSize;
|
||||||
|
|
||||||
@ -310,7 +308,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
|
|||||||
Register<0x591, u32> primitiveRestartEnable;
|
Register<0x591, u32> primitiveRestartEnable;
|
||||||
Register<0x592, u32> primitiveRestartIndex;
|
Register<0x592, u32> primitiveRestartIndex;
|
||||||
|
|
||||||
Register<0x5A1, u32> provokingVertexIsLast;
|
Register<0x5A1, type::ProvokingVertex> provokingVertex;
|
||||||
|
|
||||||
Register<0x5E7, type::ZtLayer> ztLayer;
|
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<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<0x646, u32> oglCullEnable;
|
||||||
Register<0x647, type::FrontFace> frontFace;
|
Register<0x647, type::FrontFace> oglFrontFace;
|
||||||
Register<0x648, type::CullFace> cullFace;
|
Register<0x648, type::CullFace> oglCullFace;
|
||||||
|
|
||||||
Register<0x649, u32> pixelCentreImage;
|
Register<0x649, u32> pixelCentreImage;
|
||||||
Register<0x64B, u32> viewportScaleOffsetEnable;
|
Register<0x64B, u32> viewportScaleOffsetEnable;
|
||||||
Register<0x64F, type::ViewVolumeClipControl> viewVolumeClipControl;
|
Register<0x64F, type::ViewportClipControl> viewportClipControl;
|
||||||
|
|
||||||
Register<0x652, type::PrimitiveTopologyControl> primitiveTopologyControl;
|
Register<0x652, type::PrimitiveTopologyControl> primitiveTopologyControl;
|
||||||
Register<0x65C, type::PrimitiveTopology> primitiveTopology;
|
Register<0x65C, type::PrimitiveTopology> primitiveTopology;
|
||||||
|
Loading…
Reference in New Issue
Block a user