From 96cd9c2d186766d5a445475778f971e12a3b2aca Mon Sep 17 00:00:00 2001 From: CamilleLaVey Date: Sat, 29 Nov 2025 00:30:09 -0400 Subject: [PATCH] [Re-introduced] Color output handling in SPIR-V emission --- .../spirv/emit_spirv_context_get_set.cpp | 15 +++++++++++++++ .../backend/spirv/spirv_emit_context.cpp | 17 +++++++++++++++++ .../backend/spirv/spirv_emit_context.h | 1 + src/shader_recompiler/runtime_info.h | 1 + .../renderer_vulkan/vk_pipeline_cache.cpp | 16 ++++++++++++++++ 5 files changed, 50 insertions(+) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index fb9d3dbbb2..4eb0c57421 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -483,6 +483,21 @@ void EmitSetPatch(EmitContext& ctx, IR::Patch patch, Id value) { } void EmitSetFragColor(EmitContext& ctx, u32 index, u32 component, Id value) { + const AttributeType output_type{ctx.runtime_info.color_output_types[index]}; + Id pointer_type{ctx.output_f32}; + Id store_value{value}; + switch (output_type) { + case AttributeType::SignedInt: + pointer_type = ctx.output_s32; + store_value = ctx.OpBitcast(ctx.S32[1], value); + break; + case AttributeType::UnsignedInt: + pointer_type = ctx.output_u32; + store_value = ctx.OpBitcast(ctx.U32[1], value); + break; + default: + break; + } const Id component_id{ctx.Const(component)}; const AttributeType type{ctx.runtime_info.color_output_types[index]}; if (type == AttributeType::Float) { diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 71fe2a5514..03f14a5327 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -563,6 +563,7 @@ void EmitContext::DefineCommonTypes(const Info& info) { output_f32 = Name(TypePointer(spv::StorageClass::Output, F32[1]), "output_f32"); output_u32 = Name(TypePointer(spv::StorageClass::Output, U32[1]), "output_u32"); + output_s32 = Name(TypePointer(spv::StorageClass::Output, S32[1]), "output_s32"); if (info.uses_int8 && profile.support_int8) { AddCapability(spv::Capability::Int8); @@ -1708,6 +1709,22 @@ void EmitContext::DefineOutputs(const IR::Program& program) { Decorate(frag_color[index], spv::Decoration::Location, index); Name(frag_color[index], fmt::format("frag_color{}", index)); } +#if 0 + const AttributeType output_type{runtime_info.color_output_types[index]}; + const Id vec_type = [&, output_type]() -> Id { + switch (output_type) { + case AttributeType::SignedInt: + return S32[4]; + case AttributeType::UnsignedInt: + return U32[4]; + default: + return F32[4]; + } + }(); + frag_color[index] = DefineOutput(*this, vec_type, std::nullopt); + Decorate(frag_color[index], spv::Decoration::Location, index); + Name(frag_color[index], fmt::format("frag_color{}", index)); +#endif } if (info.stores_frag_depth) { frag_depth = DefineOutput(*this, F32[1], std::nullopt); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 978b1748e4..cb1951dc6a 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -251,6 +251,7 @@ public: Id output_f32{}; Id output_u32{}; + Id output_s32{}; Id image_buffer_type{}; Id image_u32{}; diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index e6e1284762..6b6d9efe65 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -84,6 +84,7 @@ struct TransformFeedbackVarying { struct RuntimeInfo { std::array generic_input_types{}; + std::array color_output_types{}; VaryingState previous_stage_stores; std::map previous_stage_legacy_stores_mapping; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 1d0bbc8b23..a7769ce1ed 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -37,6 +37,7 @@ #include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_shader_util.h" #include "video_core/renderer_vulkan/vk_update_descriptor.h" +#include "video_core/surface.h" #include "video_core/shader_cache.h" #include "video_core/shader_environment.h" #include "video_core/shader_notify.h" @@ -108,6 +109,21 @@ Shader::CompareFunction MaxwellToCompareFunction(Maxwell::ComparisonOp compariso return {}; } +Shader::AttributeType RenderTargetAttributeType(Tegra::RenderTargetFormat format) { + if (format == Tegra::RenderTargetFormat::NONE) { + return Shader::AttributeType::Float; + } + const auto pixel_format{ + VideoCore::Surface::PixelFormatFromRenderTargetFormat(format)}; + if (!VideoCore::Surface::IsPixelFormatInteger(pixel_format)) { + return Shader::AttributeType::Float; + } + if (VideoCore::Surface::IsPixelFormatSignedInteger(pixel_format)) { + return Shader::AttributeType::SignedInt; + } + return Shader::AttributeType::UnsignedInt; +} + VkShaderStageFlagBits StageToVkStage(Shader::Stage stage) { switch (stage) { case Shader::Stage::VertexA: