From 2e96248fb6bb75cf933028358f33671dd4b5b12f Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Sat, 3 Dec 2022 14:32:54 +0000 Subject: [PATCH] Track RT format info in PackedPipelineState and move VK conv code there When caching pipelines we can't cache whole images, only their formats so refactor PackedPipelineState so that it can be used for pipeline creation, as opposed to passing in a list of attachments. --- .../maxwell_3d/packed_pipeline_state.cpp | 136 +++++++++++++++++- .../maxwell_3d/packed_pipeline_state.h | 24 +++- .../maxwell_3d/pipeline_state.cpp | 134 +++-------------- .../interconnect/maxwell_3d/pipeline_state.h | 5 +- 4 files changed, 177 insertions(+), 122 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/packed_pipeline_state.cpp b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/packed_pipeline_state.cpp index a2587bb0..5df81930 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/packed_pipeline_state.cpp +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/packed_pipeline_state.cpp @@ -10,12 +10,17 @@ #pragma clang diagnostic ignored "-Wbitfield-enum-conversion" namespace skyline::gpu::interconnect::maxwell3d { + static constexpr u8 DepthDisabledMagic{0x1f}; // Format value (unused in HW) used to signal that depth is disabled + void PackedPipelineState::SetColorRenderTargetFormat(size_t index, engine::ColorTarget::Format format) { colorRenderTargetFormats[index] = static_cast(format); } - void PackedPipelineState::SetDepthRenderTargetFormat(engine::ZtFormat format) { - depthRenderTargetFormat = static_cast(format) - static_cast(engine::ZtFormat::ZF32); + void PackedPipelineState::SetDepthRenderTargetFormat(engine::ZtFormat format, bool enabled) { + if (enabled) + depthRenderTargetFormat = static_cast(format) - static_cast(engine::ZtFormat::ZF32); + else + depthRenderTargetFormat = DepthDisabledMagic; } void PackedPipelineState::SetVertexBinding(u32 index, engine::VertexStream stream, engine::VertexStreamInstance instance) { @@ -103,6 +108,133 @@ namespace skyline::gpu::interconnect::maxwell3d { return static_cast(logicOp); } + texture::Format PackedPipelineState::GetColorRenderTargetFormat(size_t rawIndex) const { + auto format{static_cast(colorRenderTargetFormats[rawIndex])}; + #define FORMAT_CASE_BASE(engineFormat, skFormat, warn) \ + case engine::ColorTarget::Format::engineFormat: \ + if constexpr (warn) \ + Logger::Warn("Partially supported RT format: " #engineFormat " used!"); \ + return skyline::gpu::format::skFormat + + #define FORMAT_CASE(engineFormat, skFormat) FORMAT_CASE_BASE(engineFormat, skFormat, false) + #define FORMAT_CASE_WARN(engineFormat, skFormat) FORMAT_CASE_BASE(engineFormat, skFormat, true) + + switch (format) { + case engine::ColorTarget::Format::Disabled: + return texture::Format{}; + FORMAT_CASE(RF32_GF32_BF32_AF32, R32G32B32A32Float); + FORMAT_CASE(RS32_GS32_BS32_AS32, R32G32B32A32Sint); + FORMAT_CASE(RU32_GU32_BU32_AU32, R32G32B32A32Uint); + FORMAT_CASE_WARN(RF32_GF32_BF32_X32, R32G32B32A32Float); // TODO: ignore X32 component with blend + FORMAT_CASE_WARN(RS32_GS32_BS32_X32, R32G32B32A32Sint); // TODO: ^ + FORMAT_CASE_WARN(RU32_GU32_BU32_X32, R32G32B32A32Uint); // TODO: ^ + FORMAT_CASE(R16_G16_B16_A16, R16G16B16A16Unorm); + FORMAT_CASE(RN16_GN16_BN16_AN16, R16G16B16A16Snorm); + FORMAT_CASE(RS16_GS16_BS16_AS16, R16G16B16A16Sint); + FORMAT_CASE(RU16_GU16_BU16_AU16, R16G16B16A16Uint); + FORMAT_CASE(RF16_GF16_BF16_AF16, R16G16B16A16Float); + FORMAT_CASE(RF32_GF32, R32G32Float); + FORMAT_CASE(RS32_GS32, R32G32Sint); + FORMAT_CASE(RU32_GU32, R32G32Uint); + FORMAT_CASE_WARN(RF16_GF16_BF16_X16, R16G16B16A16Float); // TODO: ^^ + FORMAT_CASE(A8R8G8B8, B8G8R8A8Unorm); + FORMAT_CASE(A8RL8GL8BL8, B8G8R8A8Srgb); + FORMAT_CASE(A2B10G10R10, A2B10G10R10Unorm); + FORMAT_CASE(AU2BU10GU10RU10, A2B10G10R10Uint); + FORMAT_CASE(A8B8G8R8, R8G8B8A8Unorm); + FORMAT_CASE(A8BL8GL8RL8, R8G8B8A8Srgb); + FORMAT_CASE(AN8BN8GN8RN8, R8G8B8A8Snorm); + FORMAT_CASE(AS8BS8GS8RS8, R8G8B8A8Sint); + FORMAT_CASE(AU8BU8GU8RU8, R8G8B8A8Uint); + FORMAT_CASE(R16_G16, R16G16Unorm); + FORMAT_CASE(RN16_GN16, R16G16Snorm); + FORMAT_CASE(RS16_GS16, R16G16Sint); + FORMAT_CASE(RU16_GU16, R16G16Uint); + FORMAT_CASE(RF16_GF16, R16G16Float); + FORMAT_CASE(A2R10G10B10, A2B10G10R10Unorm); + FORMAT_CASE(BF10GF11RF11, B10G11R11Float); + FORMAT_CASE(RS32, R32Sint); + FORMAT_CASE(RU32, R32Uint); + FORMAT_CASE(RF32, R32Float); + FORMAT_CASE_WARN(X8R8G8B8, B8G8R8A8Unorm); // TODO: ^^ + FORMAT_CASE_WARN(X8RL8GL8BL8, B8G8R8A8Srgb); // TODO: ^^ + FORMAT_CASE(R5G6B5, R5G6B5Unorm); + FORMAT_CASE(A1R5G5B5, A1R5G5B5Unorm); + FORMAT_CASE(G8R8, R8G8Unorm); + FORMAT_CASE(GN8RN8, R8G8Snorm); + FORMAT_CASE(GS8RS8, R8G8Sint); + FORMAT_CASE(GU8RU8, R8G8Uint); + FORMAT_CASE(R16, R16Unorm); + FORMAT_CASE(RN16, R16Snorm); + FORMAT_CASE(RS16, R16Sint); + FORMAT_CASE(RU16, R16Uint); + FORMAT_CASE(RF16, R16Float); + FORMAT_CASE(R8, R8Unorm); + FORMAT_CASE(RN8, R8Snorm); + FORMAT_CASE(RS8, R8Sint); + FORMAT_CASE(RU8, R8Uint); + // FORMAT_CASE(A8, A8Unorm); + FORMAT_CASE_WARN(X1R5G5B5, A1R5G5B5Unorm); // TODO: ^^ + FORMAT_CASE_WARN(X8B8G8R8, R8G8B8A8Unorm); // TODO: ^^ + FORMAT_CASE_WARN(X8BL8GL8RL8, R8G8B8A8Srgb); // TODO: ^^ + FORMAT_CASE_WARN(Z1R5G5B5, A1R5G5B5Unorm); // TODO: ^^ but with zero blend + FORMAT_CASE_WARN(O1R5G5B5, A1R5G5B5Unorm); // TODO: ^^ but with one blend + FORMAT_CASE_WARN(Z8R8G8B8, B8G8R8A8Unorm); // TODO: ^^ but with zero blend + FORMAT_CASE_WARN(O8R8G8B8, B8G8R8A8Unorm); // TODO: ^^ but with one blend + // FORMAT_CASE(R32, R32Unorm); + // FORMAT_CASE(A16, A16Unorm); + // FORMAT_CASE(AF16, A16Float); + // FORMAT_CASE(AF32, A32Float); + // FORMAT_CASE(A8R8, R8A8Unorm); + // FORMAT_CASE(R16_A16, R16A16Unorm); + // FORMAT_CASE(RF16_AF16, R16A16Float); + // FORMAT_CASE(RF32_AF32, R32A32Float); + // FORMAT_CASE(B8G8R8A8, A8R8G8B8Unorm) + default: + throw exception("Unsupported colour rendertarget format: 0x{:X}", static_cast(format)); + } + + #undef FORMAT_CASE + #undef FORMAT_CASE_WARN + #undef FORMAT_CASE_BASE + } + + bool PackedPipelineState::IsColorRenderTargetEnabled(size_t rawIndex) const { + return colorRenderTargetFormats[rawIndex] != 0; + } + + size_t PackedPipelineState::GetColorRenderTargetCount() const { + for (size_t i{engine::ColorTargetCount}; i > 0 ; i--) + if (IsColorRenderTargetEnabled(i - 1)) + return i; + + return 0; + } + + texture::Format PackedPipelineState::GetDepthRenderTargetFormat() const { + if (depthRenderTargetFormat == DepthDisabledMagic) + return texture::Format{}; + + auto format{static_cast(depthRenderTargetFormat + static_cast(engine::ZtFormat::ZF32))}; + #define FORMAT_CASE(engineFormat, skFormat) \ + case engine::ZtFormat::engineFormat: \ + return skyline::gpu::format::skFormat + + switch (format) { + FORMAT_CASE(Z16, D16Unorm); + FORMAT_CASE(Z24S8, S8UintD24Unorm); + FORMAT_CASE(X8Z24, D24UnormX8Uint); + FORMAT_CASE(S8Z24, D24UnormS8Uint); + FORMAT_CASE(S8, S8Uint); + FORMAT_CASE(ZF32, D32Float); + FORMAT_CASE(ZF32_X24S8, D32FloatS8Uint); + default: + throw exception("Unsupported depth rendertarget format: 0x{:X}", static_cast(format)); + } + + #undef FORMAT_CASE + } + static u8 ConvertStencilOp(engine::StencilOps::Op op) { auto conv{[&]() { switch (op) { diff --git a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/packed_pipeline_state.h b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/packed_pipeline_state.h index d0918033..1e579a05 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/packed_pipeline_state.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/maxwell_3d/packed_pipeline_state.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include #include "common.h" @@ -67,7 +68,7 @@ namespace skyline::gpu::interconnect::maxwell3d { float pointSize; std::array vertexAttributes; std::array colorRenderTargetFormats; //!< Use {Set, Get}ColorRenderTargetFormat - std::bitset<8> activeColorTargets; + engine::CtSelect ctSelect; std::array postVtgShaderAttributeSkipMask; struct VertexBinding { @@ -105,9 +106,12 @@ namespace skyline::gpu::interconnect::maxwell3d { }; std::array transformFeedbackVaryings{}; - void SetColorRenderTargetFormat(size_t index, engine::ColorTarget::Format format); + /** + * @param rawIndex Index in HW ignoring the ctSelect register + */ + void SetColorRenderTargetFormat(size_t rawIndex, engine::ColorTarget::Format format); - void SetDepthRenderTargetFormat(engine::ZtFormat format); + void SetDepthRenderTargetFormat(engine::ZtFormat format, bool enabled); void SetVertexBinding(u32 index, engine::VertexStream stream, engine::VertexStreamInstance instance); @@ -133,6 +137,20 @@ namespace skyline::gpu::interconnect::maxwell3d { void SetAttachmentBlendState(u32 index, bool enable, engine::CtWrite writeMask, engine::BlendPerTarget blend); + /** + * @param rawIndex Index in HW ignoring the ctSelect register + */ + texture::Format GetColorRenderTargetFormat(size_t rawIndex) const; + + /** + * @param rawIndex Index in HW ignoring the ctSelect register + */ + bool IsColorRenderTargetEnabled(size_t rawIndex) const; + + size_t GetColorRenderTargetCount() const; + + texture::Format GetDepthRenderTargetFormat() const; + std::array GetStencilOpsState() const; vk::PipelineColorBlendAttachmentState GetAttachmentBlendState(u32 index) const; 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 527b9616..a37f04c6 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 @@ -8,7 +8,6 @@ #include #include #include -#include #include #include "pipeline_state.h" @@ -34,94 +33,6 @@ namespace skyline::gpu::interconnect::maxwell3d { ColorRenderTargetState::ColorRenderTargetState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine, size_t index) : engine{manager, dirtyHandle, engine}, index{index} {} - static texture::Format ConvertColorRenderTargetFormat(engine::ColorTarget::Format format) { - #define FORMAT_CASE_BASE(engineFormat, skFormat, warn) \ - case engine::ColorTarget::Format::engineFormat: \ - if constexpr (warn) \ - Logger::Warn("Partially supported RT format: " #engineFormat " used!"); \ - return skyline::gpu::format::skFormat - - #define FORMAT_CASE(engineFormat, skFormat) FORMAT_CASE_BASE(engineFormat, skFormat, false) - #define FORMAT_CASE_WARN(engineFormat, skFormat) FORMAT_CASE_BASE(engineFormat, skFormat, true) - - switch (format) { - FORMAT_CASE(RF32_GF32_BF32_AF32, R32G32B32A32Float); - FORMAT_CASE(RS32_GS32_BS32_AS32, R32G32B32A32Sint); - FORMAT_CASE(RU32_GU32_BU32_AU32, R32G32B32A32Uint); - FORMAT_CASE_WARN(RF32_GF32_BF32_X32, R32G32B32A32Float); // TODO: ignore X32 component with blend - FORMAT_CASE_WARN(RS32_GS32_BS32_X32, R32G32B32A32Sint); // TODO: ^ - FORMAT_CASE_WARN(RU32_GU32_BU32_X32, R32G32B32A32Uint); // TODO: ^ - FORMAT_CASE(R16_G16_B16_A16, R16G16B16A16Unorm); - FORMAT_CASE(RN16_GN16_BN16_AN16, R16G16B16A16Snorm); - FORMAT_CASE(RS16_GS16_BS16_AS16, R16G16B16A16Sint); - FORMAT_CASE(RU16_GU16_BU16_AU16, R16G16B16A16Uint); - FORMAT_CASE(RF16_GF16_BF16_AF16, R16G16B16A16Float); - FORMAT_CASE(RF32_GF32, R32G32Float); - FORMAT_CASE(RS32_GS32, R32G32Sint); - FORMAT_CASE(RU32_GU32, R32G32Uint); - FORMAT_CASE_WARN(RF16_GF16_BF16_X16, R16G16B16A16Float); // TODO: ^^ - FORMAT_CASE(A8R8G8B8, B8G8R8A8Unorm); - FORMAT_CASE(A8RL8GL8BL8, B8G8R8A8Srgb); - FORMAT_CASE(A2B10G10R10, A2B10G10R10Unorm); - FORMAT_CASE(AU2BU10GU10RU10, A2B10G10R10Uint); - FORMAT_CASE(A8B8G8R8, R8G8B8A8Unorm); - FORMAT_CASE(A8BL8GL8RL8, R8G8B8A8Srgb); - FORMAT_CASE(AN8BN8GN8RN8, R8G8B8A8Snorm); - FORMAT_CASE(AS8BS8GS8RS8, R8G8B8A8Sint); - FORMAT_CASE(AU8BU8GU8RU8, R8G8B8A8Uint); - FORMAT_CASE(R16_G16, R16G16Unorm); - FORMAT_CASE(RN16_GN16, R16G16Snorm); - FORMAT_CASE(RS16_GS16, R16G16Sint); - FORMAT_CASE(RU16_GU16, R16G16Uint); - FORMAT_CASE(RF16_GF16, R16G16Float); - FORMAT_CASE(A2R10G10B10, A2B10G10R10Unorm); - FORMAT_CASE(BF10GF11RF11, B10G11R11Float); - FORMAT_CASE(RS32, R32Sint); - FORMAT_CASE(RU32, R32Uint); - FORMAT_CASE(RF32, R32Float); - FORMAT_CASE_WARN(X8R8G8B8, B8G8R8A8Unorm); // TODO: ^^ - FORMAT_CASE_WARN(X8RL8GL8BL8, B8G8R8A8Srgb); // TODO: ^^ - FORMAT_CASE(R5G6B5, R5G6B5Unorm); - FORMAT_CASE(A1R5G5B5, A1R5G5B5Unorm); - FORMAT_CASE(G8R8, R8G8Unorm); - FORMAT_CASE(GN8RN8, R8G8Snorm); - FORMAT_CASE(GS8RS8, R8G8Sint); - FORMAT_CASE(GU8RU8, R8G8Uint); - FORMAT_CASE(R16, R16Unorm); - FORMAT_CASE(RN16, R16Snorm); - FORMAT_CASE(RS16, R16Sint); - FORMAT_CASE(RU16, R16Uint); - FORMAT_CASE(RF16, R16Float); - FORMAT_CASE(R8, R8Unorm); - FORMAT_CASE(RN8, R8Snorm); - FORMAT_CASE(RS8, R8Sint); - FORMAT_CASE(RU8, R8Uint); - // FORMAT_CASE(A8, A8Unorm); - FORMAT_CASE_WARN(X1R5G5B5, A1R5G5B5Unorm); // TODO: ^^ - FORMAT_CASE_WARN(X8B8G8R8, R8G8B8A8Unorm); // TODO: ^^ - FORMAT_CASE_WARN(X8BL8GL8RL8, R8G8B8A8Srgb); // TODO: ^^ - FORMAT_CASE_WARN(Z1R5G5B5, A1R5G5B5Unorm); // TODO: ^^ but with zero blend - FORMAT_CASE_WARN(O1R5G5B5, A1R5G5B5Unorm); // TODO: ^^ but with one blend - FORMAT_CASE_WARN(Z8R8G8B8, B8G8R8A8Unorm); // TODO: ^^ but with zero blend - FORMAT_CASE_WARN(O8R8G8B8, B8G8R8A8Unorm); // TODO: ^^ but with one blend - // FORMAT_CASE(R32, R32Unorm); - // FORMAT_CASE(A16, A16Unorm); - // FORMAT_CASE(AF16, A16Float); - // FORMAT_CASE(AF32, A32Float); - // FORMAT_CASE(A8R8, R8A8Unorm); - // FORMAT_CASE(R16_A16, R16A16Unorm); - // FORMAT_CASE(RF16_AF16, R16A16Float); - // FORMAT_CASE(RF32_AF32, R32A32Float); - // FORMAT_CASE(B8G8R8A8, A8R8G8B8Unorm) - default: - throw exception("Unsupported colour rendertarget format: 0x{:X}", static_cast(format)); - } - - #undef FORMAT_CASE - #undef FORMAT_CASE_WARN - #undef FORMAT_CASE_BASE - } - void ColorRenderTargetState::Flush(InterconnectContext &ctx, PackedPipelineState &packedState) { auto &target{engine->colorTarget}; packedState.SetColorRenderTargetFormat(index, target.format); @@ -132,7 +43,7 @@ namespace skyline::gpu::interconnect::maxwell3d { } GuestTexture guest{}; - guest.format = ConvertColorRenderTargetFormat(target.format); + guest.format = packedState.GetColorRenderTargetFormat(index); guest.aspect = vk::ImageAspectFlagBits::eColor; guest.baseArrayLayer = target.layerOffset; @@ -167,6 +78,7 @@ namespace skyline::gpu::interconnect::maxwell3d { view = ctx.gpu.texture.FindOrCreate(guest, ctx.executor.tag); } else { + packedState.SetColorRenderTargetFormat(index, engine::ColorTarget::Format::Disabled); view = {}; } } @@ -178,28 +90,8 @@ namespace skyline::gpu::interconnect::maxwell3d { DepthRenderTargetState::DepthRenderTargetState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine) : engine{manager, dirtyHandle, engine} {} - static texture::Format ConvertDepthRenderTargetFormat(engine::ZtFormat format) { - #define FORMAT_CASE(engineFormat, skFormat) \ - case engine::ZtFormat::engineFormat: \ - return skyline::gpu::format::skFormat - - switch (format) { - FORMAT_CASE(Z16, D16Unorm); - FORMAT_CASE(Z24S8, S8UintD24Unorm); - FORMAT_CASE(X8Z24, D24UnormX8Uint); - FORMAT_CASE(S8Z24, D24UnormS8Uint); - FORMAT_CASE(S8, S8Uint); - FORMAT_CASE(ZF32, D32Float); - FORMAT_CASE(ZF32_X24S8, D32FloatS8Uint); - default: - throw exception("Unsupported depth rendertarget format: 0x{:X}", static_cast(format)); - } - - #undef FORMAT_CASE - } - void DepthRenderTargetState::Flush(InterconnectContext &ctx, PackedPipelineState &packedState) { - packedState.SetDepthRenderTargetFormat(engine->ztFormat); + packedState.SetDepthRenderTargetFormat(engine->ztFormat, engine->ztSelect.targetCount); if (!engine->ztSelect.targetCount) { view = {}; @@ -207,7 +99,7 @@ namespace skyline::gpu::interconnect::maxwell3d { } GuestTexture guest{}; - guest.format = ConvertDepthRenderTargetFormat(engine->ztFormat); + guest.format = packedState.GetDepthRenderTargetFormat(); guest.aspect = guest.format->vkAspect; guest.baseArrayLayer = engine->ztLayer.offset; @@ -238,6 +130,7 @@ namespace skyline::gpu::interconnect::maxwell3d { view = ctx.gpu.texture.FindOrCreate(guest, ctx.executor.tag); } else { + packedState.SetDepthRenderTargetFormat(engine->ztFormat, false); view = {}; } } @@ -407,8 +300,10 @@ namespace skyline::gpu::interconnect::maxwell3d { packedState.SetLogicOp(engine->logicOp.func); for (u32 i{}; i < engine::ColorTargetCount; i++) { + bool rtEnabled{packedState.IsColorRenderTargetEnabled(packedState.ctSelect[i])}; + enabledRts.set(i, rtEnabled); auto ctWrite{[&]() { - if (!packedState.activeColorTargets.test(i)) + if (!rtEnabled) return engine::CtWrite{}; if (engine->singleCtWriteControl) @@ -417,7 +312,7 @@ namespace skyline::gpu::interconnect::maxwell3d { return engine->ctWrites[i]; }()}; - bool enable{engine->blend.enable[i] != 0 && packedState.activeColorTargets.test(i)}; + bool enable{engine->blend.enable[i] != 0 && rtEnabled}; if (engine->blendStatePerTargetEnable) packedState.SetAttachmentBlendState(i, enable, ctWrite, engine->blendPerTargets[i]); @@ -426,6 +321,14 @@ namespace skyline::gpu::interconnect::maxwell3d { } } + bool ColorBlendState::Refresh(PackedPipelineState &packedState) { + for (u32 i{}; i < engine::ColorTargetCount; i++) + if (enabledRts.test(i) != packedState.IsColorRenderTargetEnabled(packedState.ctSelect[i])) + return true; + + return false; + } + /* Transform Feedback State */ void TransformFeedbackState::EngineRegisters::DirtyBind(DirtyManager &manager, dirty::Handle handle) const { manager.Bind(handle, streamOutputEnable, streamOutControls, streamOutLayoutSelect); @@ -491,6 +394,7 @@ namespace skyline::gpu::interconnect::maxwell3d { void PipelineState::Flush(InterconnectContext &ctx, Textures &textures, ConstantBufferSet &constantBuffers, StateUpdateBuilder &builder) { packedState.dynamicStateActive = ctx.gpu.traits.supportsExtendedDynamicState; + packedState.ctSelect = ctSelect; std::array shaderBinaries; for (size_t i{}; i < engine::PipelineCount; i++) { @@ -500,11 +404,9 @@ namespace skyline::gpu::interconnect::maxwell3d { } colorAttachments.clear(); - packedState.activeColorTargets.reset(); for (size_t i{}; i < ctSelect.count; i++) { const auto &view{colorRenderTargets[ctSelect[i]].UpdateGet(ctx, packedState).view.get()}; colorAttachments.push_back(view); - packedState.activeColorTargets.set(i); if (view) ctx.executor.AttachTexture(view); 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 ba5492e9..1683a90f 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 @@ -212,7 +212,7 @@ namespace skyline::gpu::interconnect::maxwell3d { void Flush(PackedPipelineState &packedState); }; - class ColorBlendState : dirty::ManualDirty { + class ColorBlendState : dirty::RefreshableManualDirty { public: struct EngineRegisters { const engine::LogicOp &logicOp; @@ -227,11 +227,14 @@ namespace skyline::gpu::interconnect::maxwell3d { private: dirty::BoundSubresource engine; + std::bitset enabledRts{}; public: ColorBlendState(dirty::Handle dirtyHandle, DirtyManager &manager, const EngineRegisters &engine); void Flush(PackedPipelineState &packedState); + + bool Refresh(PackedPipelineState &packedState); }; class TransformFeedbackState : dirty::ManualDirty {