Introduce Maxwell 3D shader state

Simple state holder that hashes the stored shader and reads it into a buffer
This commit is contained in:
Billy Laws 2022-09-09 22:46:43 +01:00
parent 6865f0bdaf
commit 405d26fc22
5 changed files with 76 additions and 15 deletions

View File

@ -12,6 +12,7 @@
#include <gpu.h>
#include <vulkan/vulkan_core.h>
#include "pipeline_state.h"
#include "shader_state.h"
#include "soc/gm20b/engines/maxwell/types.h"
namespace skyline::gpu::interconnect::maxwell3d {
@ -753,6 +754,18 @@ namespace skyline::gpu::interconnect::maxwell3d {
}
}
/* Global Shader Config State */
void GlobalShaderConfigState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
manager.Bind(handle, postVtgShaderAttributeSkipMask, bindlessTexture);
}
GlobalShaderConfigState::GlobalShaderConfigState(const EngineRegisters &engine) : engine{engine} {}
void GlobalShaderConfigState::Update(PackedPipelineState &packedState) {
packedState.postVtgShaderAttributeSkipMask = engine.postVtgShaderAttributeSkipMask;
packedState.bindlessTextureConstantBufferSlotSelect = engine.bindlessTexture.constantBufferSlotSelect;
}
/* Pipeline State */
void PipelineState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const {
auto bindFunc{[&](auto &regs) { regs.DirtyBind(manager, handle); }};
@ -764,6 +777,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
PipelineState::PipelineState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine)
: engine{manager, dirtyHandle, engine},
shaders{util::MergeInto<dirty::ManualDirtyState<IndividualShaderState>, engine::PipelineCount>(manager, engine.shadersRegisters, util::IncrementingT<u8>{})},
colorRenderTargets{util::MergeInto<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount>(manager, engine.colorRenderTargetsRegisters, util::IncrementingT<size_t>{})},
depthRenderTarget{manager, engine.depthRenderTargetRegisters},
vertexInput{manager, engine.vertexInputRegisters},
@ -771,7 +785,8 @@ namespace skyline::gpu::interconnect::maxwell3d {
rasterization{manager, engine.rasterizationRegisters},
depthStencil{manager, engine.depthStencilRegisters},
colorBlend{manager, engine.colorBlendRegisters},
directState{engine.inputAssemblyRegisters} {}
directState{engine.inputAssemblyRegisters},
globalShaderConfig{engine.globalShaderConfigRegisters} {}
void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) {
boost::container::static_vector<TextureView *, engine::ColorTargetCount> colorAttachments;
@ -790,6 +805,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
}; */
depthStencil.Update(packedState);
colorBlend.Update(packedState);
globalShaderConfig.Update(packedState);
constexpr std::array<vk::DynamicState, 9> dynamicStates{
vk::DynamicState::eViewport,

View File

@ -6,7 +6,7 @@
#include <boost/container/static_vector.hpp>
#include <gpu/texture/texture.h>
#include "common.h"
#include "soc/gm20b/engines/maxwell/types.h"
#include "shader_state.h"
namespace skyline::gpu::interconnect::maxwell3d {
/**
@ -47,11 +47,13 @@ namespace skyline::gpu::interconnect::maxwell3d {
bool stencilTestEnable : 1;
bool logicOpEnable : 1;
vk::LogicOp logicOp : 4; //!< Use {Set, Get}LogicOp
u8 bindlessTextureConstantBufferSlotSelect : 5;
};
u32 patchSize;
std::array<engine::VertexAttribute, engine::VertexAttributeCount> vertexAttributes;
std::array<u8, engine::ColorTargetCount> colorRenderTargetFormats; //!< Use {Set, Get}ColorRenderTargetFormat
std::array<u32, 8> postVtgShaderAttributeSkipMask;
struct VertexBinding {
u16 stride : 12;
@ -287,12 +289,31 @@ namespace skyline::gpu::interconnect::maxwell3d {
void Flush(PackedPipelineState &packedState);
};
class GlobalShaderConfigState {
public:
struct EngineRegisters {
const std::array<u32, 8> &postVtgShaderAttributeSkipMask;
const engine::BindlessTexture &bindlessTexture;
void DirtyBind(DirtyManager &manager, dirty::Handle handle) const;
};
private:
EngineRegisters engine;
public:
GlobalShaderConfigState(const EngineRegisters &engine);
void Update(PackedPipelineState &packedState);
};
/**
* @brief Holds all GPU state for a pipeline, any changes to this will result in a pipeline cache lookup
*/
class PipelineState : dirty::ManualDirty {
public:
struct EngineRegisters {
std::array<IndividualShaderState::EngineRegisters, engine::PipelineCount> shadersRegisters;
std::array<ColorRenderTargetState::EngineRegisters, engine::ColorTargetCount> colorRenderTargetsRegisters;
DepthRenderTargetState::EngineRegisters depthRenderTargetRegisters;
VertexInputState::EngineRegisters vertexInputRegisters;
@ -301,6 +322,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
RasterizationState::EngineRegisters rasterizationRegisters;
DepthStencilState::EngineRegisters depthStencilRegisters;
ColorBlendState::EngineRegisters colorBlendRegisters;
GlobalShaderConfigState::EngineRegisters globalShaderConfigRegisters;
void DirtyBind(DirtyManager &manager, dirty::Handle handle) const;
};
@ -310,6 +332,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
dirty::BoundSubresource<EngineRegisters> engine;
std::array<dirty::ManualDirtyState<IndividualShaderState>, engine::PipelineCount> shaders;
std::array<dirty::ManualDirtyState<ColorRenderTargetState>, engine::ColorTargetCount> colorRenderTargets;
dirty::ManualDirtyState<DepthRenderTargetState> depthRenderTarget;
dirty::ManualDirtyState<VertexInputState> vertexInput;
@ -317,7 +340,7 @@ namespace skyline::gpu::interconnect::maxwell3d {
dirty::ManualDirtyState<RasterizationState> rasterization;
dirty::ManualDirtyState<DepthStencilState> depthStencil;
dirty::ManualDirtyState<ColorBlendState> colorBlend;
GlobalShaderConfigState globalShaderConfig;
public:
DirectPipelineState directState;

View File

@ -858,9 +858,15 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
};
static_assert(sizeof(BindGroup) == (sizeof(u32) * 8));
struct BindlessTexture {
u8 constantBufferSlotSelect : 5;
u32 _pad0_ : 27;
};
static_assert(sizeof(BindlessTexture) == sizeof(u32));
constexpr static size_t PipelineStageConstantBufferCount{18}; //!< Maximum amount of constant buffers that can be bound to a single pipeline stage
constexpr static size_t ShaderStageCount{6}; //!< Amount of shader stages on Maxwell 3D
constexpr static size_t PipelineCount{6}; //!< Amount of shader stages on Maxwell 3D
/**
* @brief All the shader programs stages that Maxwell3D supports for draws
@ -879,19 +885,31 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
/**
* @brief The arguments to set a shader program for a pipeline stage
*/
struct SetProgramInfo {
struct {
struct Pipeline {
struct Shader {
enum class Type : u8 {
VertexCullBeforeFetch = 0,
Vertex = 1,
TessellationInit = 2,
Tessellation = 3,
Geometry = 4,
Pixel = 5,
};
bool enable : 1;
u8 _pad0_ : 3;
ShaderStage stage : 4;
Type type : 4;
u32 _pad1_ : 24;
} info;
u32 offset; //!< Offset from the base shader memory IOVA
} shader;
u32 programOffset; //!< Offset from the base shader memory IOVA
u32 _pad2_;
u32 gprCount; //!< Amount of GPRs used by the shader program
u32 _pad3_[12];
u8 registerCount; //!< Amount of GPRs used by the shader program
u32 _pad3_ : 24;
u8 bindingGroup : 3;
u32 _pad4_ : 29;
u32 _pad5_[11];
};
static_assert(sizeof(SetProgramInfo) == (sizeof(u32) * 0x10));
static_assert(sizeof(Pipeline) == (sizeof(u32) * 0x10));
struct ProvokingVertex {
enum class Value : u8 {

View File

@ -14,6 +14,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
static gpu::interconnect::maxwell3d::PipelineState::EngineRegisters MakePipelineStateRegisters(const Maxwell3D::Registers &registers) {
return {
.shadersRegisters = util::MergeInto<REGTYPE(IndividualShaderState), type::PipelineCount>(*registers.pipelines, *registers.programRegion),
.colorRenderTargetsRegisters = util::MergeInto<REGTYPE(ColorRenderTargetState), type::ColorTargetCount>(*registers.colorTargets),
.depthRenderTargetRegisters = {*registers.ztSize, *registers.ztOffset, *registers.ztFormat, *registers.ztBlockSize, *registers.ztArrayPitch, *registers.ztSelect, *registers.ztLayer},
.vertexInputRegisters = {*registers.vertexStreams, *registers.vertexStreamInstance, *registers.vertexAttributes},
@ -22,6 +23,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
.rasterizationRegisters = {*registers.rasterEnable, *registers.frontPolygonMode, *registers.backPolygonMode, *registers.oglCullEnable, *registers.oglCullFace, *registers.windowOrigin, *registers.oglFrontFace, *registers.viewportClipControl, *registers.polyOffset, *registers.provokingVertex},
.depthStencilRegisters = {*registers.depthTestEnable, *registers.depthWriteEnable, *registers.depthFunc, *registers.depthBoundsTestEnable, *registers.stencilTestEnable, *registers.twoSidedStencilTestEnable, *registers.stencilOps, *registers.stencilBack},
.colorBlendRegisters = {*registers.logicOp, *registers.singleCtWriteControl, *registers.ctWrites, *registers.blendStatePerTargetEnable, *registers.blendPerTargets, *registers.blend},
.globalShaderConfigRegisters = {*registers.postVtgShaderAttributeSkipMask, *registers.bindlessTexture}
};
}

View File

@ -189,6 +189,8 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x48D, bool> linkedTscHandle; //!< If enabled, the TSC index in a bindless texture handle is ignored and the TIC index is used as the TSC index, otherwise the TSC index from the bindless texture handle is used
Register<0x490, std::array<u32, 8>> postVtgShaderAttributeSkipMask;
Register<0x4B3, u32> depthTestEnable;
Register<0x4B9, u32> blendStatePerTargetEnable;
Register<0x4BA, u32> depthWriteEnable;
@ -253,7 +255,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x56F, float> depthBias;
Register<0x581, type::PointCoordReplace> pointCoordReplace;
Register<0x582, Address> setProgramRegion;
Register<0x582, Address> programRegion;
Register<0x585, u32> end; //!< Method-only register with no real value, used after calling vertexBeginGl to invoke the draw
@ -339,7 +341,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x7C0, std::array<Address, type::VertexStreamCount>> vertexStreamLimits; //!< A per-VBO IOVA denoting the end of the vertex buffer
Register<0x800, std::array<type::SetProgramInfo, type::ShaderStageCount>> setProgram;
Register<0x800, std::array<type::Pipeline, type::PipelineCount>> pipelines;
Register<0x8C0, u32[0x20]> firmwareCall;
@ -357,7 +359,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x900, std::array<type::BindGroup, type::PipelineStageCount>> bindGroups; //!< Binds constant buffers to pipeline stages
Register<0x982, u32> bindlessTextureConstantBufferIndex; //!< The index of the constant buffer containing bindless texture descriptors
Register<0x982, type::BindlessTexture> bindlessTexture; //!< The index of the constant buffer containing bindless texture descriptors
Register<0xA00, std::array<u32, (type::TransformFeedbackVaryingCount / sizeof(u32)) * type::StreamOutBufferCount>> transformFeedbackVaryings;
};