From 405d26fc22a6f73fd4862875ea67d5ff3765ed22 Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Fri, 9 Sep 2022 22:46:43 +0100 Subject: [PATCH] Introduce Maxwell 3D shader state Simple state holder that hashes the stored shader and reads it into a buffer --- .../maxwell_3d/pipeline_state.cpp | 18 +++++++++- .../interconnect/maxwell_3d/pipeline_state.h | 27 ++++++++++++-- .../skyline/soc/gm20b/engines/maxwell/types.h | 36 ++++++++++++++----- .../skyline/soc/gm20b/engines/maxwell_3d.cpp | 2 ++ .../skyline/soc/gm20b/engines/maxwell_3d.h | 8 +++-- 5 files changed, 76 insertions(+), 15 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp index 4c16a07c..5de5e3c9 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.cpp @@ -12,6 +12,7 @@ #include #include #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 ®s) { 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, engine::PipelineCount>(manager, engine.shadersRegisters, util::IncrementingT{})}, colorRenderTargets{util::MergeInto, engine::ColorTargetCount>(manager, engine.colorRenderTargetsRegisters, util::IncrementingT{})}, 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 colorAttachments; @@ -790,6 +805,7 @@ namespace skyline::gpu::interconnect::maxwell3d { }; */ depthStencil.Update(packedState); colorBlend.Update(packedState); + globalShaderConfig.Update(packedState); constexpr std::array dynamicStates{ vk::DynamicState::eViewport, diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h index 32c580ce..0df876c0 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/pipeline_state.h @@ -6,7 +6,7 @@ #include #include #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 vertexAttributes; std::array colorRenderTargetFormats; //!< Use {Set, Get}ColorRenderTargetFormat + std::array 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 &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 shadersRegisters; std::array 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 engine; + std::array, engine::PipelineCount> shaders; std::array, engine::ColorTargetCount> colorRenderTargets; dirty::ManualDirtyState depthRenderTarget; dirty::ManualDirtyState vertexInput; @@ -317,7 +340,7 @@ namespace skyline::gpu::interconnect::maxwell3d { dirty::ManualDirtyState rasterization; dirty::ManualDirtyState depthStencil; dirty::ManualDirtyState colorBlend; - + GlobalShaderConfigState globalShaderConfig; public: DirectPipelineState directState; diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h index 84f5af9d..411fd407 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h @@ -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 { diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp index d472a64b..6cfd97e4 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp @@ -14,6 +14,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { static gpu::interconnect::maxwell3d::PipelineState::EngineRegisters MakePipelineStateRegisters(const Maxwell3D::Registers ®isters) { return { + .shadersRegisters = util::MergeInto(*registers.pipelines, *registers.programRegion), .colorRenderTargetsRegisters = util::MergeInto(*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} }; } diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h index d2060f4f..e7b7478b 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h @@ -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> 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> vertexStreamLimits; //!< A per-VBO IOVA denoting the end of the vertex buffer - Register<0x800, std::array> setProgram; + Register<0x800, std::array> pipelines; Register<0x8C0, u32[0x20]> firmwareCall; @@ -357,7 +359,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x900, std::array> 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> transformFeedbackVaryings; };