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 a648e3e9..678054ff 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 @@ -628,6 +628,182 @@ namespace skyline::gpu::interconnect::maxwell3d { depthStencilState.back = ConvertStencilOpsState(stencilBack); }; + /* Color Blend State */ + void ColorBlendState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const { + manager.Bind(handle, logicOp, singleCtWriteControl, ctWrites, blendStatePerTargetEnable, blendPerTargets, blend); + } + + ColorBlendState::ColorBlendState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine) : engine{manager, dirtyHandle, engine} {} + + vk::LogicOp ConvertLogicOpFunc(engine::LogicOp::Func func) { + switch (func) { + case engine::LogicOp::Func::Clear: + return vk::LogicOp::eClear; + case engine::LogicOp::Func::And: + return vk::LogicOp::eAnd; + case engine::LogicOp::Func::AndReverse: + return vk::LogicOp::eAndReverse; + case engine::LogicOp::Func::Copy: + return vk::LogicOp::eCopy; + case engine::LogicOp::Func::AndInverted: + return vk::LogicOp::eAndInverted; + case engine::LogicOp::Func::Noop: + return vk::LogicOp::eNoOp; + case engine::LogicOp::Func::Xor: + return vk::LogicOp::eXor; + case engine::LogicOp::Func::Or: + return vk::LogicOp::eOr; + case engine::LogicOp::Func::Nor: + return vk::LogicOp::eNor; + case engine::LogicOp::Func::Equiv: + return vk::LogicOp::eEquivalent; + case engine::LogicOp::Func::Invert: + return vk::LogicOp::eInvert; + case engine::LogicOp::Func::OrReverse: + return vk::LogicOp::eOrReverse; + case engine::LogicOp::Func::CopyInverted: + return vk::LogicOp::eCopyInverted; + case engine::LogicOp::Func::OrInverted: + return vk::LogicOp::eOrInverted; + case engine::LogicOp::Func::Nand: + return vk::LogicOp::eNand; + case engine::LogicOp::Func::Set: + return vk::LogicOp::eSet; + default: + throw exception("Invalid logical operation type: 0x{:X}", static_cast(func)); + } + } + + static vk::ColorComponentFlags ConvertColorWriteMask(engine::CtWrite write) { + return vk::ColorComponentFlags{ + write.rEnable ? vk::ColorComponentFlagBits::eR : vk::ColorComponentFlags{} | + write.gEnable ? vk::ColorComponentFlagBits::eG : vk::ColorComponentFlags{} | + write.bEnable ? vk::ColorComponentFlagBits::eB : vk::ColorComponentFlags{} | + write.aEnable ? vk::ColorComponentFlagBits::eA : vk::ColorComponentFlags{} + }; + } + + static vk::BlendOp ConvertBlendOp(engine::BlendOp op) { + switch (op) { + case engine::BlendOp::D3DAdd: + case engine::BlendOp::OglFuncAdd: + return vk::BlendOp::eAdd; + case engine::BlendOp::D3DSubtract: + case engine::BlendOp::OglFuncSubtract: + return vk::BlendOp::eSubtract; + case engine::BlendOp::D3DRevSubtract: + case engine::BlendOp::OglFuncReverseSubtract: + return vk::BlendOp::eReverseSubtract; + case engine::BlendOp::D3DMin: + case engine::BlendOp::OglMin: + return vk::BlendOp::eMin; + case engine::BlendOp::D3DMax: + case engine::BlendOp::OglMax: + return vk::BlendOp::eMax; + default: + throw exception("Invalid blend operation: 0x{:X}", static_cast(op)); + } + } + + static vk::BlendFactor ConvertBlendFactor(engine::BlendCoeff coeff) { + switch (coeff) { + case engine::BlendCoeff::OglZero: + case engine::BlendCoeff::D3DZero: + return vk::BlendFactor::eZero; + case engine::BlendCoeff::OglOne: + case engine::BlendCoeff::D3DOne: + return vk::BlendFactor::eOne; + case engine::BlendCoeff::OglSrcColor: + case engine::BlendCoeff::D3DSrcColor: + return vk::BlendFactor::eSrcColor; + case engine::BlendCoeff::OglOneMinusSrcColor: + case engine::BlendCoeff::D3DInvSrcColor: + return vk::BlendFactor::eOneMinusSrcColor; + case engine::BlendCoeff::OglSrcAlpha: + case engine::BlendCoeff::D3DSrcAlpha: + return vk::BlendFactor::eSrcAlpha; + case engine::BlendCoeff::OglOneMinusSrcAlpha: + case engine::BlendCoeff::D3DInvSrcAlpha: + return vk::BlendFactor::eOneMinusSrcAlpha; + case engine::BlendCoeff::OglDstAlpha: + case engine::BlendCoeff::D3DDstAlpha: + return vk::BlendFactor::eDstAlpha; + case engine::BlendCoeff::OglOneMinusDstAlpha: + case engine::BlendCoeff::D3DInvDstAlpha: + return vk::BlendFactor::eOneMinusDstAlpha; + case engine::BlendCoeff::OglDstColor: + case engine::BlendCoeff::D3DDstColor: + return vk::BlendFactor::eDstColor; + case engine::BlendCoeff::OglOneMinusDstColor: + case engine::BlendCoeff::D3DInvDstColor: + return vk::BlendFactor::eOneMinusDstColor; + case engine::BlendCoeff::OglSrcAlphaSaturate: + case engine::BlendCoeff::D3DSrcAlphaSaturate: + return vk::BlendFactor::eSrcAlphaSaturate; + case engine::BlendCoeff::OglConstantColor: + case engine::BlendCoeff::D3DBlendCoeff: + return vk::BlendFactor::eConstantColor; + case engine::BlendCoeff::OglOneMinusConstantColor: + case engine::BlendCoeff::D3DInvBlendCoeff: + return vk::BlendFactor::eOneMinusConstantColor; + case engine::BlendCoeff::OglConstantAlpha: + return vk::BlendFactor::eConstantAlpha; + case engine::BlendCoeff::OglOneMinusConstantAlpha: + return vk::BlendFactor::eOneMinusConstantAlpha; + case engine::BlendCoeff::OglSrc1Color: + case engine::BlendCoeff::D3DSrc1Color: + return vk::BlendFactor::eSrc1Color; + case engine::BlendCoeff::OglInvSrc1Color: + case engine::BlendCoeff::D3DInvSrc1Color: + return vk::BlendFactor::eOneMinusSrc1Color; + case engine::BlendCoeff::OglSrc1Alpha: + case engine::BlendCoeff::D3DSrc1Alpha: + return vk::BlendFactor::eSrc1Alpha; + case engine::BlendCoeff::OglInvSrc1Alpha: + case engine::BlendCoeff::D3DInvSrc1Alpha: + return vk::BlendFactor::eOneMinusSrc1Alpha; + default: + throw exception("Invalid blend coefficient type: 0x{:X}", static_cast(coeff)); + } + } + + void ColorBlendState::Flush(InterconnectContext &ctx, size_t attachmentCount) { + if (engine->logicOp.enable) { + if (ctx.gpu.traits.supportsLogicOp) { + colorBlendState.logicOpEnable = true; + colorBlendState.logicOp = ConvertLogicOpFunc(engine->logicOp.func); + } else { + Logger::Warn("Cannot enable framebuffer logical operation without host GPU support!"); + } + } + + auto convertBlendState{[](vk::PipelineColorBlendAttachmentState &attachmentBlendState, const auto &blend) { + attachmentBlendState.colorBlendOp = ConvertBlendOp(blend.colorOp); + attachmentBlendState.srcColorBlendFactor = ConvertBlendFactor(blend.colorSourceCoeff); + attachmentBlendState.dstColorBlendFactor = ConvertBlendFactor(blend.colorDestCoeff); + attachmentBlendState.alphaBlendOp = ConvertBlendOp(blend.alphaOp); + attachmentBlendState.srcAlphaBlendFactor = ConvertBlendFactor(blend.alphaSourceCoeff); + attachmentBlendState.dstAlphaBlendFactor = ConvertBlendFactor(blend.alphaDestCoeff); + }}; + + for (size_t i{}; i < engine::ColorTargetCount; i++) { + auto &attachmentBlendState{attachmentBlendStates[i]}; + attachmentBlendState.blendEnable = engine->blend.enable[i]; + attachmentBlendState.colorWriteMask = ConvertColorWriteMask(engine->singleCtWriteControl ? engine->ctWrites[0] : engine->ctWrites[i]); + if (engine->blendStatePerTargetEnable) + convertBlendState(attachmentBlendState, engine->blendPerTargets[i]); + else + convertBlendState(attachmentBlendState, engine->blend); + } + + colorBlendState.attachmentCount = static_cast(attachmentCount); + colorBlendState.pAttachments = attachmentBlendStates.data(); + } + + void ColorBlendState::Refresh(InterconnectContext &ctx, size_t attachmentCount) { + colorBlendState.attachmentCount = static_cast(attachmentCount); + } + /* Pipeline State */ void PipelineState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const { auto bindFunc{[&](auto ®s) { regs.DirtyBind(manager, handle); }}; @@ -642,14 +818,18 @@ namespace skyline::gpu::interconnect::maxwell3d { colorRenderTargets{util::MergeInto, engine::ColorTargetCount>(manager, engine.colorRenderTargetsRegisters)}, depthRenderTarget{manager, engine.depthRenderTargetRegisters}, rasterization{manager, engine.rasterizationRegisters}, - depthStencil{manager, engine.depthStencilRegisters} {} + depthStencil{manager, engine.depthStencilRegisters}, + colorBlend{manager, engine.colorBlendRegisters} {} void PipelineState::Flush(InterconnectContext &ctx, StateUpdateBuilder &builder) { - auto updateFunc{[&](auto &stateElem, auto &&... args) { stateElem.Update(ctx, args...); }}; - ranges::for_each(colorRenderTargets, updateFunc); - updateFunc(depthRenderTarget); + boost::container::static_vector colorAttachments; + for (auto &colorRenderTarget : colorRenderTargets) + if (auto view{colorRenderTarget.UpdateGet(ctx).view}; view) + colorAttachments.push_back(view.get()); - auto vertexState{directState.vertexInput.Build(ctx, engine->vertexInputRegisters)}; + TextureView *depthAttachment{depthRenderTarget.UpdateGet(ctx).view.get()}; + + auto vertexInputState{directState.vertexInput.Build(ctx, engine->vertexInputRegisters)}; const auto &inputAssemblyState{directState.inputAssembly.Build()}; const auto &tessellationState{directState.tessellation.Build()}; const auto &rasterizationState{rasterization.UpdateGet().rasterizationState}; @@ -657,8 +837,7 @@ namespace skyline::gpu::interconnect::maxwell3d { .rasterizationSamples = vk::SampleCountFlagBits::e1 }; const auto &depthStencilState{depthStencil.UpdateGet().depthStencilState}; - - + const auto &colorBlendState{colorBlend.UpdateGet(ctx, colorAttachments.size()).colorBlendState}; } std::shared_ptr PipelineState::GetColorRenderTargetForClear(InterconnectContext &ctx, size_t index) { 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 aef92d00..b0eecb2a 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 @@ -163,7 +163,7 @@ namespace skyline::gpu::interconnect::maxwell3d { dirty::BoundSubresource engine; public: - vk::StructureChain rasterizationState; + vk::StructureChain rasterizationState{}; RasterizationState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine); @@ -189,13 +189,40 @@ namespace skyline::gpu::interconnect::maxwell3d { dirty::BoundSubresource engine; public: - vk::PipelineDepthStencilStateCreateInfo depthStencilState; + vk::PipelineDepthStencilStateCreateInfo depthStencilState{}; DepthStencilState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine); void Flush(); }; + class ColorBlendState : dirty::RefreshableManualDirty { + public: + struct EngineRegisters { + const engine::LogicOp &logicOp; + const u32 &singleCtWriteControl; + const std::array &ctWrites; + const u32 &blendStatePerTargetEnable; + const std::array &blendPerTargets; + const engine::Blend &blend; + + void DirtyBind(DirtyManager &manager, dirty::Handle handle) const; + }; + + private: + dirty::BoundSubresource engine; + std::array attachmentBlendStates; + + public: + vk::PipelineColorBlendStateCreateInfo colorBlendState{}; + + ColorBlendState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine); + + void Flush(InterconnectContext &ctx, size_t attachmentCount); + + void Refresh(InterconnectContext &ctx, size_t attachmentCount); + }; + /** * @brief Holds all GPU state for a pipeline, any changes to this will result in a pipeline cache lookup */ @@ -209,6 +236,7 @@ namespace skyline::gpu::interconnect::maxwell3d { TessellationState::EngineRegisters tessellationRegisters; RasterizationState::EngineRegisters rasterizationRegisters; DepthStencilState::EngineRegisters depthStencilRegisters; + ColorBlendState::EngineRegisters colorBlendRegisters; void DirtyBind(DirtyManager &manager, dirty::Handle handle) const; }; @@ -220,6 +248,7 @@ namespace skyline::gpu::interconnect::maxwell3d { dirty::ManualDirtyState depthRenderTarget; dirty::ManualDirtyState rasterization; dirty::ManualDirtyState depthStencil; + dirty::ManualDirtyState colorBlend; public: 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 854784c8..84f5af9d 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 @@ -481,59 +481,55 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type { constexpr static size_t BlendColorChannelCount{4}; //!< The amount of color channels in operations such as blending enum class BlendOp : u32 { - Add = 1, - Subtract = 2, - ReverseSubtract = 3, - Minimum = 4, - Maximum = 5, - - AddGL = 0x8006, - MinimumGL = 0x8007, - MaximumGL = 0x8008, - SubtractGL = 0x800A, - ReverseSubtractGL = 0x800B, + OglFuncSubtract = 0x0000800A, + OglFuncReverseSubtract = 0x0000800B, + OglFuncAdd = 0x00008006, + OglMin = 0x00008007, + OglMax = 0x00008008, + D3DAdd = 0x00000001, + D3DSubtract = 0x00000002, + D3DRevSubtract = 0x00000003, + D3DMin = 0x00000004, + D3DMax = 0x00000005, }; - enum class BlendFactor : u32 { - Zero = 0x1, - One = 0x2, - SourceColor = 0x3, - OneMinusSourceColor = 0x4, - SourceAlpha = 0x5, - OneMinusSourceAlpha = 0x6, - DestAlpha = 0x7, - OneMinusDestAlpha = 0x8, - DestColor = 0x9, - OneMinusDestColor = 0xA, - SourceAlphaSaturate = 0xB, - Source1Color = 0x10, - OneMinusSource1Color = 0x11, - Source1Alpha = 0x12, - OneMinusSource1Alpha = 0x13, - ConstantColor = 0x61, - OneMinusConstantColor = 0x62, - ConstantAlpha = 0x63, - OneMinusConstantAlpha = 0x64, - - ZeroGL = 0x4000, - OneGL = 0x4001, - SourceColorGL = 0x4300, - OneMinusSourceColorGL = 0x4301, - SourceAlphaGL = 0x4302, - OneMinusSourceAlphaGL = 0x4303, - DestAlphaGL = 0x4304, - OneMinusDestAlphaGL = 0x4305, - DestColorGL = 0x4306, - OneMinusDestColorGL = 0x4307, - SourceAlphaSaturateGL = 0x4308, - ConstantColorGL = 0xC001, - OneMinusConstantColorGL = 0xC002, - ConstantAlphaGL = 0xC003, - OneMinusConstantAlphaGL = 0xC004, - Source1ColorGL = 0xC900, - OneMinusSource1ColorGL = 0xC901, - Source1AlphaGL = 0xC902, - OneMinusSource1AlphaGL = 0xC903, + enum class BlendCoeff : u32 { + OglZero = 0x4000, + OglOne = 0x4001, + OglSrcColor = 0x4300, + OglOneMinusSrcColor = 0x4301, + OglSrcAlpha = 0x4302, + OglOneMinusSrcAlpha = 0x4303, + OglDstAlpha = 0x4304, + OglOneMinusDstAlpha = 0x4305, + OglDstColor = 0x4306, + OglOneMinusDstColor = 0x4307, + OglSrcAlphaSaturate = 0x4308, + OglConstantColor = 0xC001, + OglOneMinusConstantColor = 0xC002, + OglConstantAlpha = 0xC003, + OglOneMinusConstantAlpha = 0xC004, + OglSrc1Color = 0xC900, + OglInvSrc1Color = 0xC901, + OglSrc1Alpha = 0xC902, + OglInvSrc1Alpha = 0xC903, + D3DZero = 0x1, + D3DOne = 0x2, + D3DSrcColor = 0x3, + D3DInvSrcColor = 0x4, + D3DSrcAlpha = 0x5, + D3DInvSrcAlpha = 0x6, + D3DDstAlpha = 0x7, + D3DInvDstAlpha = 0x8, + D3DDstColor = 0x9, + D3DInvDstColor = 0xA, + D3DSrcAlphaSaturate = 0xB, + D3DBlendCoeff = 0xE, + D3DInvBlendCoeff = 0xF, + D3DSrc1Color = 0x10, + D3DInvSrc1Color = 0x11, + D3DSrc1Alpha = 0x12, + D3DInvSrc1Alpha = 0x13, }; struct ZtSelect { @@ -710,17 +706,21 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type { }; static_assert(sizeof(ViewportClipControl) == sizeof(u32)); - union ColorWriteMask { + union CtWrite { u32 raw; struct { - u8 red : 4; - u8 green : 4; - u8 blue : 4; - u8 alpha : 4; + bool rEnable : 1; + u8 _pad0_ : 3; + bool gEnable : 1; + u8 _pad1_ : 3; + bool bEnable : 1; + u8 _pad2_ : 3; + bool aEnable : 1; + u32 _pad3_ : 19; }; }; - static_assert(sizeof(ColorWriteMask) == sizeof(u32)); + static_assert(sizeof(CtWrite) == sizeof(u32)); /** * @brief A method call which causes a layer of an RT to be cleared with a channel mask @@ -823,28 +823,6 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type { }; static_assert(sizeof(SemaphoreInfo) == sizeof(u32)); - /** - * @brief The logical operations that can be performed on the framebuffer after the fragment shader - */ - enum class ColorLogicOp : u32 { - Clear = 0x1500, - And = 0x1501, - AndReverse = 0x1502, - Copy = 0x1503, - AndInverted = 0x1504, - Noop = 0x1505, - Xor = 0x1506, - Or = 0x1507, - Nor = 0x1508, - Equiv = 0x1509, - Invert = 0x150A, - OrReverse = 0x150B, - CopyInverted = 0x150C, - OrInverted = 0x150D, - Nand = 0x150E, - Set = 0x150F, - }; - constexpr static size_t PipelineStageCount{5}; //!< Amount of pipeline stages on Maxwell 3D /** @@ -978,6 +956,34 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type { }; static_assert(sizeof(VertexStream) == sizeof(u32) * 4); + struct BlendPerTarget { + bool seperateForAlpha : 1; + u32 _pad0_ : 31; + BlendOp colorOp; + BlendCoeff colorSourceCoeff; + BlendCoeff colorDestCoeff; + BlendOp alphaOp; + BlendCoeff alphaSourceCoeff; + BlendCoeff alphaDestCoeff; + u32 _pad_; + }; + + struct Blend { + bool seperateForAlpha : 1; + u32 _pad0_ : 31; + BlendOp colorOp; + BlendCoeff colorSourceCoeff; + BlendCoeff colorDestCoeff; + BlendOp alphaOp; + BlendCoeff alphaSourceCoeff; + bool globalColorKeyEnable : 1; + u32 _pad1_ : 31; + BlendCoeff alphaDestCoeff; + bool singleRopControlEnable : 1; + u32 _pad2_ : 31; + std::array enable; + }; + struct WindowOrigin { bool lowerLeft : 1; u8 _pad0_ : 3; @@ -1119,5 +1125,28 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type { }; static_assert(sizeof(TessellationParameters) == sizeof(u32)); + struct LogicOp { + bool enable : 1; + u32 _pad0_ : 31; + enum class Func : u32 { + Clear = 0x1500, + And = 0x1501, + AndReverse = 0x1502, + Copy = 0x1503, + AndInverted = 0x1504, + Noop = 0x1505, + Xor = 0x1506, + Or = 0x1507, + Nor = 0x1508, + Equiv = 0x1509, + Invert = 0x150A, + OrReverse = 0x150B, + CopyInverted = 0x150C, + OrInverted = 0x150D, + Nand = 0x150E, + Set = 0x150F + } func; + }; + #pragma pack(pop) } 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 5921480e..8056b3f4 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 @@ -21,6 +21,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { .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}, .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}, }; } 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 3967094f..d2060f4f 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 @@ -190,7 +190,7 @@ 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<0x4B3, u32> depthTestEnable; - Register<0x4B9, u32> independentBlendEnable; + Register<0x4B9, u32> blendStatePerTargetEnable; Register<0x4BA, u32> depthWriteEnable; Register<0x4BB, u32> alphaTestEnable; Register<0x4C3, type::CompareFunc> depthFunc; @@ -206,22 +206,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { }; Register<0x4C7, std::array> blendConsts; - struct BlendStateCommon { - u32 seperateAlpha; // 0x4CF - type::BlendOp colorOp; // 0x4D0 - type::BlendFactor colorSrcFactor; // 0x4D1 - type::BlendFactor colorDstFactor; // 0x4D2 - type::BlendOp alphaOp; // 0x4D3 - type::BlendFactor alphaSrcFactor; // 0x4D4 - u32 pad; // 0x4D5 - type::BlendFactor alphaDstFactor; // 0x4D6 - - u32 enable; // 0x4D7 - }; - Register<0x4CF, BlendStateCommon> blendStateCommon; - - Register<0x4D8, std::array> rtBlendEnable; - + Register<0x4CF, type::Blend> blend; Register<0x4E0, u32> stencilTestEnable; Register<0x4E1, type::StencilOps> stencilOps; @@ -336,14 +321,10 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x66F, u32> depthBoundsTestEnable; - struct ColorLogicOp { - u32 enable; - type::ColorLogicOp type; - }; - Register<0x671, ColorLogicOp> colorLogicOp; + Register<0x671, type::LogicOp> logicOp; Register<0x674, type::ClearSurface> clearSurface; - Register<0x680, std::array> colorWriteMask; + Register<0x680, std::array> ctWrites; struct Semaphore { Address address; // 0x6C0 @@ -354,17 +335,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0x700, std::array> vertexStreams; - struct IndependentBlend { - u32 seperateAlpha; - type::BlendOp colorOp; - type::BlendFactor colorSrcFactor; - type::BlendFactor colorDstFactor; - type::BlendOp alphaOp; - type::BlendFactor alphaSrcFactor; - type::BlendFactor alphaDstFactor; - u32 _pad_; - }; - Register<0x780, std::array> independentBlend; + Register<0x780, std::array> blendPerTargets; Register<0x7C0, std::array> vertexStreamLimits; //!< A per-VBO IOVA denoting the end of the vertex buffer