diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 2fd0f3bd1a..4bff810547 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -14,25 +14,6 @@ namespace Shader::Backend::SPIRV { namespace { -Id GetResultType(EmitContext& ctx, NumericType numeric_type) { - switch (numeric_type) { - case NumericType::Float: - return ctx.F32[4]; - case NumericType::SignedInt: - return ctx.S32[4]; - case NumericType::UnsignedInt: - return ctx.U32[4]; - } - throw LogicError("Invalid numeric type {}", static_cast(numeric_type)); -} - -NumericType GetTextureNumericType(EmitContext& ctx, const IR::TextureInstInfo& info) { - if (info.type == TextureType::Buffer) { - return ctx.texture_buffers.at(info.descriptor_index).numeric_type; - } - return ctx.textures.at(info.descriptor_index).numeric_type; -} - class ImageOperands { public: [[maybe_unused]] static constexpr bool ImageSampleOffsetAllowed = false; @@ -220,10 +201,10 @@ Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info, const IR::Value& ind const TextureBufferDefinition& def{ctx.texture_buffers.at(info.descriptor_index)}; if (def.count > 1) { const Id idx{index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index)}; - const Id ptr{ctx.OpAccessChain(def.pointer_type, def.id, idx)}; - return ctx.OpLoad(def.image_type, ptr); + const Id ptr{ctx.OpAccessChain(ctx.image_buffer_type, def.id, idx)}; + return ctx.OpLoad(ctx.image_buffer_type, ptr); } - return ctx.OpLoad(def.image_type, def.id); + return ctx.OpLoad(ctx.image_buffer_type, def.id); } else { const TextureDefinition& def{ctx.textures.at(info.descriptor_index)}; if (def.count > 1) { @@ -235,24 +216,23 @@ Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info, const IR::Value& ind } } -std::pair Image(EmitContext& ctx, const IR::Value& index, - IR::TextureInstInfo info) { +std::pair Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { if (info.type == TextureType::Buffer) { const ImageBufferDefinition def{ctx.image_buffers.at(info.descriptor_index)}; if (def.count > 1) { const Id idx{index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index)}; const Id ptr{ctx.OpAccessChain(def.pointer_type, def.id, idx)}; - return {ctx.OpLoad(def.image_type, ptr), def.numeric_type}; + return {ctx.OpLoad(def.image_type, ptr), def.is_integer}; } - return {ctx.OpLoad(def.image_type, def.id), def.numeric_type}; + return {ctx.OpLoad(def.image_type, def.id), def.is_integer}; } else { const ImageDefinition def{ctx.images.at(info.descriptor_index)}; if (def.count > 1) { const Id idx{index.IsImmediate() ? ctx.Const(index.U32()) : ctx.Def(index)}; const Id ptr{ctx.OpAccessChain(def.pointer_type, def.id, idx)}; - return {ctx.OpLoad(def.image_type, ptr), def.numeric_type}; + return {ctx.OpLoad(def.image_type, ptr), def.is_integer}; } - return {ctx.OpLoad(def.image_type, def.id), def.numeric_type}; + return {ctx.OpLoad(def.image_type, def.id), def.is_integer}; } } @@ -481,9 +461,8 @@ Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& if (ctx.stage == Stage::Fragment) { const ImageOperands operands(ctx, info.has_bias != 0, false, info.has_lod_clamp != 0, bias_lc, offset); - const Id result_type{GetResultType(ctx, GetTextureNumericType(ctx, info))}; return Emit(&EmitContext::OpImageSparseSampleImplicitLod, - &EmitContext::OpImageSampleImplicitLod, ctx, inst, result_type, + &EmitContext::OpImageSampleImplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, info, index), coords, operands.MaskOptional(), operands.Span()); } else { // We can't use implicit lods on non-fragment stages on SPIR-V. Maxwell hardware behaves as @@ -491,9 +470,8 @@ Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& // derivatives const Id lod{ctx.Const(0.0f)}; const ImageOperands operands(ctx, false, true, info.has_lod_clamp != 0, lod, offset); - const Id result_type{GetResultType(ctx, GetTextureNumericType(ctx, info))}; return Emit(&EmitContext::OpImageSparseSampleExplicitLod, - &EmitContext::OpImageSampleExplicitLod, ctx, inst, result_type, + &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); } } @@ -502,14 +480,12 @@ Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& Id lod, const IR::Value& offset) { const auto info{inst->Flags()}; const ImageOperands operands(ctx, false, true, false, lod, offset); - const NumericType numeric_type{GetTextureNumericType(ctx, info)}; - const Id result_type{GetResultType(ctx, numeric_type)}; Id result = Emit(&EmitContext::OpImageSparseSampleExplicitLod, - &EmitContext::OpImageSampleExplicitLod, ctx, inst, result_type, + &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); #ifdef ANDROID - if (numeric_type == NumericType::Float && Settings::values.fix_bloom_effects.GetValue()) { + if (Settings::values.fix_bloom_effects.GetValue()) { result = ctx.OpVectorTimesScalar(ctx.F32[4], result, ctx.Const(0.98f)); } #endif @@ -553,9 +529,8 @@ Id EmitImageGather(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id if (ctx.profile.need_gather_subpixel_offset) { coords = ImageGatherSubpixelOffset(ctx, info, TextureImage(ctx, info, index), coords); } - const Id result_type{GetResultType(ctx, GetTextureNumericType(ctx, info))}; return Emit(&EmitContext::OpImageSparseGather, &EmitContext::OpImageGather, ctx, inst, - result_type, Texture(ctx, info, index), coords, ctx.Const(info.gather_component), + ctx.F32[4], Texture(ctx, info, index), coords, ctx.Const(info.gather_component), operands.MaskOptional(), operands.Span()); } @@ -583,10 +558,8 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c lod = Id{}; } const ImageOperands operands(lod, ms); - const Id result_type{GetResultType(ctx, GetTextureNumericType(ctx, info))}; - return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, - result_type, TextureImage(ctx, info, index), coords, operands.MaskOptional(), - operands.Span()); + return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4], + TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span()); } Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id lod, @@ -636,9 +609,8 @@ Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I ctx.Def(offset), {}, lod_clamp) : ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, info.num_derivatives, offset, lod_clamp); - const Id result_type{GetResultType(ctx, GetTextureNumericType(ctx, info))}; return Emit(&EmitContext::OpImageSparseSampleExplicitLod, - &EmitContext::OpImageSampleExplicitLod, ctx, inst, result_type, + &EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4], Texture(ctx, info, index), coords, operands.Mask(), operands.Span()); } @@ -648,11 +620,11 @@ Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id co LOG_WARNING(Shader_SPIRV, "Typeless image read not supported by host"); return ctx.ConstantNull(ctx.U32[4]); } - const auto [image, numeric_type] = Image(ctx, index, info); - const Id result_type{GetResultType(ctx, numeric_type)}; + const auto [image, is_integer] = Image(ctx, index, info); + const Id result_type{is_integer ? ctx.U32[4] : ctx.F32[4]}; Id color{Emit(&EmitContext::OpImageSparseRead, &EmitContext::OpImageRead, ctx, inst, result_type, image, coords, std::nullopt, std::span{})}; - if (numeric_type == NumericType::Float) { + if (!is_integer) { color = ctx.OpBitcast(ctx.U32[4], color); } return color; @@ -660,8 +632,8 @@ Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id co void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color) { const auto info{inst->Flags()}; - const auto [image, numeric_type] = Image(ctx, index, info); - if (numeric_type == NumericType::Float) { + const auto [image, is_integer] = Image(ctx, index, info); + if (!is_integer) { color = ctx.OpBitcast(ctx.F32[4], color); } ctx.OpImageWrite(image, coords, color); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 957fe6e15b..ffa9aa7e1a 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -29,21 +29,9 @@ enum class Operation { FPMax, }; -Id GetNumericTypeId(EmitContext& ctx, NumericType numeric_type) { - switch (numeric_type) { - case NumericType::Float: - return ctx.F32[1]; - case NumericType::SignedInt: - return ctx.S32[1]; - case NumericType::UnsignedInt: - return ctx.U32[1]; - } - throw InvalidArgument("Invalid numeric type {}", static_cast(numeric_type)); -} - Id ImageType(EmitContext& ctx, const TextureDescriptor& desc) { const spv::ImageFormat format{spv::ImageFormat::Unknown}; - const Id type{GetNumericTypeId(ctx, desc.numeric_type)}; + const Id type{ctx.F32[1]}; const bool depth{desc.is_depth}; const bool ms{desc.is_multisample}; switch (desc.type) { @@ -1317,26 +1305,22 @@ void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) { if (info.texture_buffer_descriptors.empty()) { return; } + const spv::ImageFormat format{spv::ImageFormat::Unknown}; + image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format); + + const Id type{TypePointer(spv::StorageClass::UniformConstant, image_buffer_type)}; texture_buffers.reserve(info.texture_buffer_descriptors.size()); for (const TextureBufferDescriptor& desc : info.texture_buffer_descriptors) { if (desc.count != 1) { throw NotImplementedException("Array of texture buffers"); } - const spv::ImageFormat format{spv::ImageFormat::Unknown}; - const Id image_type{ - TypeImage(GetNumericTypeId(*this, desc.numeric_type), spv::Dim::Buffer, 0U, false, - false, 1, format)}; - const Id type{TypePointer(spv::StorageClass::UniformConstant, image_type)}; const Id id{AddGlobalVariable(type, spv::StorageClass::UniformConstant)}; Decorate(id, spv::Decoration::Binding, binding); Decorate(id, spv::Decoration::DescriptorSet, 0U); Name(id, NameOf(stage, desc, "texbuf")); texture_buffers.push_back({ .id = id, - .image_type = image_type, - .pointer_type = type, .count = desc.count, - .numeric_type = desc.numeric_type, }); if (profile.supported_spirv >= 0x00010400) { interfaces.push_back(id); @@ -1349,7 +1333,7 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) { image_buffers.reserve(info.image_buffer_descriptors.size()); for (const ImageBufferDescriptor& desc : info.image_buffer_descriptors) { const spv::ImageFormat format{GetImageFormat(desc.format)}; - const Id sampled_type{GetNumericTypeId(*this, desc.numeric_type)}; + const Id sampled_type{desc.is_integer ? U32[1] : F32[1]}; const Id image_type{ TypeImage(sampled_type, spv::Dim::Buffer, false, false, false, 2, format)}; const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)}; @@ -1362,7 +1346,7 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) { .image_type = image_type, .pointer_type = pointer_type, .count = desc.count, - .numeric_type = desc.numeric_type, + .is_integer = desc.is_integer, }); if (profile.supported_spirv >= 0x00010400) { interfaces.push_back(id); @@ -1389,7 +1373,6 @@ void EmitContext::DefineTextures(const Info& info, u32& binding, u32& scaling_in .image_type = image_type, .count = desc.count, .is_multisample = desc.is_multisample, - .numeric_type = desc.numeric_type, }); if (profile.supported_spirv >= 0x00010400) { interfaces.push_back(id); @@ -1405,7 +1388,7 @@ void EmitContext::DefineTextures(const Info& info, u32& binding, u32& scaling_in void EmitContext::DefineImages(const Info& info, u32& binding, u32& scaling_index) { images.reserve(info.image_descriptors.size()); for (const ImageDescriptor& desc : info.image_descriptors) { - const Id sampled_type{GetNumericTypeId(*this, desc.numeric_type)}; + const Id sampled_type{desc.is_integer ? U32[1] : F32[1]}; const Id image_type{ImageType(*this, desc, sampled_type)}; const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_type)}; const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; @@ -1417,7 +1400,7 @@ void EmitContext::DefineImages(const Info& info, u32& binding, u32& scaling_inde .image_type = image_type, .pointer_type = pointer_type, .count = desc.count, - .numeric_type = desc.numeric_type, + .is_integer = desc.is_integer, }); if (profile.supported_spirv >= 0x00010400) { interfaces.push_back(id); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index 396022eddf..de56809a98 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -41,15 +41,11 @@ struct TextureDefinition { Id image_type; u32 count; bool is_multisample; - NumericType numeric_type; }; struct TextureBufferDefinition { Id id; - Id image_type; - Id pointer_type; u32 count; - NumericType numeric_type; }; struct ImageBufferDefinition { @@ -57,7 +53,7 @@ struct ImageBufferDefinition { Id image_type; Id pointer_type; u32 count; - NumericType numeric_type; + bool is_integer; }; struct ImageDefinition { @@ -65,7 +61,7 @@ struct ImageDefinition { Id image_type; Id pointer_type; u32 count; - NumericType numeric_type; + bool is_integer; }; struct UniformDefinitions { diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp index a1405b225f..6c466545d1 100644 --- a/src/shader_recompiler/ir_opt/texture_pass.cpp +++ b/src/shader_recompiler/ir_opt/texture_pass.cpp @@ -19,7 +19,6 @@ #include "shader_recompiler/host_translate_info.h" #include "shader_recompiler/ir_opt/passes.h" #include "shader_recompiler/shader_info.h" -#include "video_core/surface.h" namespace Shader::Optimization { namespace { @@ -34,16 +33,6 @@ using TextureInstVector = boost::container::small_vector; constexpr u32 DESCRIPTOR_SIZE = 8; constexpr u32 DESCRIPTOR_SIZE_SHIFT = static_cast(std::countr_zero(DESCRIPTOR_SIZE)); -NumericType GetNumericType(TexturePixelFormat format) { - const auto pixel_format = static_cast(format); - if (!VideoCore::Surface::IsPixelFormatInteger(pixel_format)) { - return NumericType::Float; - } - return VideoCore::Surface::IsPixelFormatSignedInteger(pixel_format) - ? NumericType::SignedInt - : NumericType::UnsignedInt; -} - IR::Opcode IndexedInstruction(const IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::BindlessImageSampleImplicitLod: @@ -436,8 +425,7 @@ public: u32 Add(const TextureBufferDescriptor& desc) { return Add(texture_buffer_descriptors, desc, [&desc](const auto& existing) { - return desc.numeric_type == existing.numeric_type && - desc.cbuf_index == existing.cbuf_index && + return desc.cbuf_index == existing.cbuf_index && desc.cbuf_offset == existing.cbuf_offset && desc.shift_left == existing.shift_left && desc.secondary_cbuf_index == existing.secondary_cbuf_index && @@ -456,13 +444,13 @@ public: })}; image_buffer_descriptors[index].is_written |= desc.is_written; image_buffer_descriptors[index].is_read |= desc.is_read; + image_buffer_descriptors[index].is_integer |= desc.is_integer; return index; } u32 Add(const TextureDescriptor& desc) { const u32 index{Add(texture_descriptors, desc, [&desc](const auto& existing) { return desc.type == existing.type && desc.is_depth == existing.is_depth && - desc.numeric_type == existing.numeric_type && desc.has_secondary == existing.has_secondary && desc.cbuf_index == existing.cbuf_index && desc.cbuf_offset == existing.cbuf_offset && @@ -486,6 +474,7 @@ public: })}; image_descriptors[index].is_written |= desc.is_written; image_descriptors[index].is_read |= desc.is_read; + image_descriptors[index].is_integer |= desc.is_integer; return index; } @@ -657,13 +646,13 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo } const bool is_written{inst->GetOpcode() != IR::Opcode::ImageRead}; const bool is_read{inst->GetOpcode() != IR::Opcode::ImageWrite}; - const NumericType numeric_type{GetNumericType(ReadTexturePixelFormatCached(env, cbuf))}; + const bool is_integer{IsTexturePixelFormatIntegerCached(env, cbuf)}; if (flags.type == TextureType::Buffer) { index = descriptors.Add(ImageBufferDescriptor{ .format = flags.image_format, .is_written = is_written, .is_read = is_read, - .numeric_type = numeric_type, + .is_integer = is_integer, .cbuf_index = cbuf.index, .cbuf_offset = cbuf.offset, .count = cbuf.count, @@ -675,7 +664,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo .format = flags.image_format, .is_written = is_written, .is_read = is_read, - .numeric_type = numeric_type, + .is_integer = is_integer, .cbuf_index = cbuf.index, .cbuf_offset = cbuf.offset, .count = cbuf.count, @@ -687,7 +676,6 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo default: if (flags.type == TextureType::Buffer) { index = descriptors.Add(TextureBufferDescriptor{ - .numeric_type = GetNumericType(ReadTexturePixelFormatCached(env, cbuf)), .has_secondary = cbuf.has_secondary, .cbuf_index = cbuf.index, .cbuf_offset = cbuf.offset, @@ -703,7 +691,6 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo .type = flags.type, .is_depth = flags.is_depth != 0, .is_multisample = is_multisample, - .numeric_type = GetNumericType(ReadTexturePixelFormatCached(env, cbuf)), .has_secondary = cbuf.has_secondary, .cbuf_index = cbuf.index, .cbuf_offset = cbuf.offset, diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index 87dd14fa46..dfacc06802 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h @@ -38,12 +38,6 @@ enum class TextureType : u32 { }; constexpr u32 NUM_TEXTURE_TYPES = 9; -enum class NumericType : u8 { - Float, - SignedInt, - UnsignedInt, -}; - enum class TexturePixelFormat { A8B8G8R8_UNORM, A8B8G8R8_SNORM, @@ -183,7 +177,6 @@ struct StorageBufferDescriptor { }; struct TextureBufferDescriptor { - NumericType numeric_type; bool has_secondary; u32 cbuf_index; u32 cbuf_offset; @@ -202,7 +195,7 @@ struct ImageBufferDescriptor { ImageFormat format; bool is_written; bool is_read; - NumericType numeric_type; + bool is_integer; u32 cbuf_index; u32 cbuf_offset; u32 count; @@ -216,7 +209,6 @@ struct TextureDescriptor { TextureType type; bool is_depth; bool is_multisample; - NumericType numeric_type; bool has_secondary; u32 cbuf_index; u32 cbuf_offset; @@ -236,7 +228,7 @@ struct ImageDescriptor { ImageFormat format; bool is_written; bool is_read; - NumericType numeric_type; + bool is_integer; u32 cbuf_index; u32 cbuf_offset; u32 count; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index f20127ce81..9786b6e900 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -893,8 +893,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { VK_COLOR_COMPONENT_A_BIT, }; const auto& blend{key.state.attachments[index]}; - const PixelFormat color_format{DecodeFormat(key.state.color_formats[index])}; - const bool supports_blending = !VideoCore::Surface::IsPixelFormatInteger(color_format); + const bool supports_blending = !VideoCore::Surface::IsPixelFormatInteger(key.color_formats[index]); const std::array mask{blend.Mask()}; VkColorComponentFlags write_mask{}; for (size_t i = 0; i < mask_table.size(); ++i) {