diff --git a/README.md b/README.md index 144aa857a..14d92a4f2 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 4030. +This is the source code for early-access 4031. ## Legal Notice diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 9d9c4eff5..c61eac635 100755 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -196,42 +196,34 @@ Id Texture(EmitContext& ctx, IR::TextureInstInfo info, [[maybe_unused]] const IR } Id TextureImage(EmitContext& ctx, IR::TextureInstInfo info, const IR::Value& index) { + if (!index.IsImmediate() || index.U32() != 0) { + throw NotImplementedException("Indirect image indexing"); + } if (info.type == TextureType::Buffer) { const TextureBufferDefinition& def{ctx.texture_buffers.at(info.descriptor_index)}; if (def.count > 1) { - const Id buffer_pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))}; - return ctx.OpLoad(ctx.image_buffer_type, buffer_pointer); - } else { - return ctx.OpLoad(ctx.image_buffer_type, def.id); + throw NotImplementedException("Indirect texture sample"); } + return ctx.OpLoad(ctx.image_buffer_type, def.id); } else { const TextureDefinition& def{ctx.textures.at(info.descriptor_index)}; if (def.count > 1) { - const Id texture_pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))}; - return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, texture_pointer)); - } else { - return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); + throw NotImplementedException("Indirect texture sample"); } + return ctx.OpImage(def.image_type, ctx.OpLoad(def.sampled_type, def.id)); } } -Id Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { +std::pair Image(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { + if (!index.IsImmediate() || index.U32() != 0) { + throw NotImplementedException("Indirect image indexing"); + } if (info.type == TextureType::Buffer) { const ImageBufferDefinition def{ctx.image_buffers.at(info.descriptor_index)}; - if (def.count > 1) { - const Id image_pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))}; - return ctx.OpLoad(def.image_type, image_pointer); - } else { - return ctx.OpLoad(def.image_type, def.id); - } + 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 image_pointer{ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index))}; - return ctx.OpLoad(def.image_type, image_pointer); - } else { - return ctx.OpLoad(def.image_type, def.id); - } + return {ctx.OpLoad(def.image_type, def.id), def.is_integer}; } } @@ -574,13 +566,23 @@ 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]); } - return Emit(&EmitContext::OpImageSparseRead, &EmitContext::OpImageRead, ctx, inst, ctx.U32[4], - Image(ctx, index, info), coords, std::nullopt, std::span{}); + 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 (!is_integer) { + color = ctx.OpBitcast(ctx.U32[4], color); + } + return color; } void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color) { const auto info{inst->Flags()}; - ctx.OpImageWrite(Image(ctx, index, info), coords, color); + const auto [image, is_integer] = Image(ctx, index, info); + if (!is_integer) { + color = ctx.OpBitcast(ctx.F32[4], color); + } + ctx.OpImageWrite(image, coords, color); } Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index) { diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp index 808fa9b62..fd09b32a6 100755 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image_atomic.cpp @@ -7,21 +7,13 @@ namespace Shader::Backend::SPIRV { namespace { -Id ImagePointer(EmitContext& ctx, const IR::Value& index, IR::TextureInstInfo info) { +Id Image(EmitContext& ctx, IR::TextureInstInfo info) { if (info.type == TextureType::Buffer) { const ImageBufferDefinition def{ctx.image_buffers.at(info.descriptor_index)}; - if (def.count > 1) { - return ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index)); - } else { - return def.id; - } + return def.id; } else { const ImageDefinition def{ctx.images.at(info.descriptor_index)}; - if (def.count > 1) { - return ctx.OpAccessChain(def.pointer_type, def.id, ctx.Def(index)); - } else { - return def.id; - } + return def.id; } } @@ -33,12 +25,15 @@ std::pair AtomicArgs(EmitContext& ctx) { Id ImageAtomicU32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id value, Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id)) { + if (!index.IsImmediate() || index.U32() != 0) { + // TODO: handle layers + throw NotImplementedException("Image indexing"); + } const auto info{inst->Flags()}; - const Id image_pointer{ImagePointer(ctx, index, info)}; - const Id texel_pointer{ - ctx.OpImageTexelPointer(ctx.image_u32, image_pointer, coords, ctx.Const(0U))}; + const Id image{Image(ctx, info)}; + const Id pointer{ctx.OpImageTexelPointer(ctx.image_u32, image, coords, ctx.Const(0U))}; const auto [scope, semantics]{AtomicArgs(ctx)}; - return (ctx.*atomic_func)(ctx.U32[1], texel_pointer, scope, semantics, value); + return (ctx.*atomic_func)(ctx.U32[1], pointer, scope, semantics, value); } } // Anonymous namespace diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 706a479a3..d42dde17c 100755 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -74,28 +74,19 @@ spv::ImageFormat GetImageFormat(ImageFormat format) { throw InvalidArgument("Invalid image format {}", format); } -Id GetImageSampledType(EmitContext& ctx, const ImageDescriptor& desc) { - if (desc.is_float) { - return ctx.F32[1]; - } else { - return ctx.U32[1]; - } -} - -Id ImageType(EmitContext& ctx, const ImageDescriptor& desc) { +Id ImageType(EmitContext& ctx, const ImageDescriptor& desc, Id sampled_type) { const spv::ImageFormat format{GetImageFormat(desc.format)}; - const Id type{GetImageSampledType(ctx, desc)}; switch (desc.type) { case TextureType::Color1D: - return ctx.TypeImage(type, spv::Dim::Dim1D, false, false, false, 2, format); + return ctx.TypeImage(sampled_type, spv::Dim::Dim1D, false, false, false, 2, format); case TextureType::ColorArray1D: - return ctx.TypeImage(type, spv::Dim::Dim1D, false, true, false, 2, format); + return ctx.TypeImage(sampled_type, spv::Dim::Dim1D, false, true, false, 2, format); case TextureType::Color2D: - return ctx.TypeImage(type, spv::Dim::Dim2D, false, false, false, 2, format); + return ctx.TypeImage(sampled_type, spv::Dim::Dim2D, false, false, false, 2, format); case TextureType::ColorArray2D: - return ctx.TypeImage(type, spv::Dim::Dim2D, false, true, false, 2, format); + return ctx.TypeImage(sampled_type, spv::Dim::Dim2D, false, true, false, 2, format); case TextureType::Color3D: - return ctx.TypeImage(type, spv::Dim::Dim3D, false, false, false, 2, format); + return ctx.TypeImage(sampled_type, spv::Dim::Dim3D, false, false, false, 2, format); case TextureType::Buffer: throw NotImplementedException("Image buffer"); default: @@ -1253,20 +1244,18 @@ void EmitContext::DefineTextureBuffers(const Info& info, u32& binding) { const spv::ImageFormat format{spv::ImageFormat::Unknown}; image_buffer_type = TypeImage(F32[1], spv::Dim::Buffer, 0U, false, false, 1, format); - const Id pointer_type{TypePointer(spv::StorageClass::UniformConstant, image_buffer_type)}; + 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) { - LOG_WARNING(Shader_SPIRV, "Array of texture buffers"); + throw NotImplementedException("Array of texture buffers"); } - const Id desc_type{DescType(*this, image_buffer_type, pointer_type, desc.count)}; - const Id id{AddGlobalVariable(desc_type, spv::StorageClass::UniformConstant)}; + 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, - .pointer_type = pointer_type, .count = desc.count, }); if (profile.supported_spirv >= 0x00010400) { @@ -1280,10 +1269,12 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) { image_buffers.reserve(info.image_buffer_descriptors.size()); for (const ImageBufferDescriptor& desc : info.image_buffer_descriptors) { if (desc.count != 1) { - LOG_WARNING(Shader_SPIRV, "Array of image buffers"); + throw NotImplementedException("Array of image buffers"); } const spv::ImageFormat format{GetImageFormat(desc.format)}; - const Id image_type{TypeImage(U32[1], spv::Dim::Buffer, false, false, false, 2, format)}; + 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)}; const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; Decorate(id, spv::Decoration::Binding, binding); @@ -1292,8 +1283,8 @@ void EmitContext::DefineImageBuffers(const Info& info, u32& binding) { image_buffers.push_back({ .id = id, .image_type = image_type, - .pointer_type = pointer_type, .count = desc.count, + .is_integer = desc.is_integer, }); if (profile.supported_spirv >= 0x00010400) { interfaces.push_back(id); @@ -1336,20 +1327,20 @@ void EmitContext::DefineImages(const Info& info, u32& binding, u32& scaling_inde images.reserve(info.image_descriptors.size()); for (const ImageDescriptor& desc : info.image_descriptors) { if (desc.count != 1) { - LOG_WARNING(Shader_SPIRV, "Array of images"); + throw NotImplementedException("Array of images"); } - const Id image_type{ImageType(*this, desc)}; + 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 desc_type{DescType(*this, image_type, pointer_type, desc.count)}; - const Id id{AddGlobalVariable(desc_type, spv::StorageClass::UniformConstant)}; + const Id id{AddGlobalVariable(pointer_type, spv::StorageClass::UniformConstant)}; Decorate(id, spv::Decoration::Binding, binding); Decorate(id, spv::Decoration::DescriptorSet, 0U); Name(id, NameOf(stage, desc, "img")); images.push_back({ .id = id, .image_type = image_type, - .pointer_type = pointer_type, .count = desc.count, + .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 c443c4c7b..609e555c5 100755 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -40,22 +40,21 @@ struct TextureDefinition { struct TextureBufferDefinition { Id id; - Id pointer_type; u32 count; }; struct ImageBufferDefinition { Id id; Id image_type; - Id pointer_type; u32 count; + bool is_integer; }; struct ImageDefinition { Id id; Id image_type; - Id pointer_type; u32 count; + bool is_integer; }; struct UniformDefinitions { diff --git a/src/shader_recompiler/environment.h b/src/shader_recompiler/environment.h index 631f17db4..da0ffa4da 100755 --- a/src/shader_recompiler/environment.h +++ b/src/shader_recompiler/environment.h @@ -24,6 +24,8 @@ public: [[nodiscard]] virtual TexturePixelFormat ReadTexturePixelFormat(u32 raw_handle) = 0; + [[nodiscard]] virtual bool IsTexturePixelFormatInteger(u32 raw_handle) = 0; + [[nodiscard]] virtual u32 ReadViewportTransformState() = 0; [[nodiscard]] virtual u32 TextureBoundBuffer() const = 0; diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index 85f91a86c..3ae9196bf 100755 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc @@ -512,7 +512,7 @@ OPCODE(ImageQueryDimensions, U32x4, Opaq OPCODE(ImageQueryLod, F32x4, Opaque, Opaque, ) OPCODE(ImageGradient, F32x4, Opaque, Opaque, Opaque, Opaque, Opaque, ) OPCODE(ImageRead, U32x4, Opaque, Opaque, ) -OPCODE(ImageWrite, Void, Opaque, Opaque, Opaque, ) +OPCODE(ImageWrite, Void, Opaque, Opaque, U32x4, ) OPCODE(IsTextureScaled, U1, U32, ) OPCODE(IsImageScaled, U1, U32, ) diff --git a/src/shader_recompiler/host_translate_info.h b/src/shader_recompiler/host_translate_info.h index 384f3456b..9cea8a5d9 100755 --- a/src/shader_recompiler/host_translate_info.h +++ b/src/shader_recompiler/host_translate_info.h @@ -19,10 +19,8 @@ struct HostTranslateInfo { u32 min_ssbo_alignment{}; ///< Minimum alignment supported by the device for SSBOs bool support_geometry_shader_passthrough{}; ///< True when the device supports geometry ///< passthrough shaders - bool support_conditional_barrier{}; ///< True when the device supports barriers in conditional - ///< control flow - bool support_ufloat_write_as_uint{}; ///< True when the device supports writing float images - ///< as bitcasts to uint + bool support_conditional_barrier{}; ///< True when the device supports barriers in conditional + ///< control flow }; } // namespace Shader diff --git a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp index 0af93de68..6cfa518bd 100755 --- a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp +++ b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp @@ -815,6 +815,15 @@ bool FindGradient3DDerivatives(std::array& results, IR::Value coor return true; } +void ConvertDerivatives(std::array& results, IR::IREmitter& ir) { + for (size_t i = 0; i < 3; i++) { + if (results[i].Type() == IR::Type::U32) { + results[i] = results[i].IsImmediate() ? ir.Imm32(Common::BitCast(results[i].U32())) + : ir.BitCast(IR::U32(results[i])); + } + } +} + void FoldImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) { IR::TextureInstInfo info = inst.Flags(); auto orig_opcode = inst.GetOpcode(); @@ -831,12 +840,14 @@ void FoldImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) { if (!offset.IsImmediate()) { return; } + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; IR::Inst* const inst2 = coords.InstRecursive(); std::array, 3> results_matrix; for (size_t i = 0; i < 3; i++) { if (!FindGradient3DDerivatives(results_matrix[i], inst2->Arg(i).Resolve())) { return; } + ConvertDerivatives(results_matrix[i], ir); } IR::F32 lod_clamp{}; if (info.has_lod_clamp != 0) { @@ -846,7 +857,6 @@ void FoldImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) { lod_clamp = IR::F32{bias_lc}; } } - IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; IR::Value new_coords = ir.CompositeConstruct(results_matrix[0][0], results_matrix[1][0], results_matrix[2][0]); IR::Value derivatives_1 = ir.CompositeConstruct(results_matrix[0][1], results_matrix[0][2], diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp index abdfe1686..156bf66eb 100755 --- a/src/shader_recompiler/ir_opt/texture_pass.cpp +++ b/src/shader_recompiler/ir_opt/texture_pass.cpp @@ -372,8 +372,8 @@ TexturePixelFormat ReadTexturePixelFormat(Environment& env, const ConstBufferAdd return env.ReadTexturePixelFormat(GetTextureHandle(env, cbuf)); } -bool TexturePixelFormatIsFloat(Environment& env, const ConstBufferAddr& cbuf) { - return ReadTexturePixelFormat(env, cbuf) == TexturePixelFormat::B10G11R11_FLOAT; +bool IsTexturePixelFormatInteger(Environment& env, const ConstBufferAddr& cbuf) { + return env.IsTexturePixelFormatInteger(GetTextureHandle(env, cbuf)); } class Descriptors { @@ -407,6 +407,7 @@ 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; } @@ -432,11 +433,11 @@ public: return desc.type == existing.type && desc.format == existing.format && desc.cbuf_index == existing.cbuf_index && desc.cbuf_offset == existing.cbuf_offset && desc.count == existing.count && - desc.size_shift == existing.size_shift && desc.is_float == existing.is_float; + desc.size_shift == existing.size_shift; })}; - // TODO: handle is_float? 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; } @@ -474,6 +475,20 @@ void PatchImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) { ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 1)))))); } +bool IsPixelFormatSNorm(TexturePixelFormat pixel_format) { + switch (pixel_format) { + case TexturePixelFormat::A8B8G8R8_SNORM: + case TexturePixelFormat::R8G8_SNORM: + case TexturePixelFormat::R8_SNORM: + case TexturePixelFormat::R16G16B16A16_SNORM: + case TexturePixelFormat::R16G16_SNORM: + case TexturePixelFormat::R16_SNORM: + return true; + default: + return false; + } +} + void PatchTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_format) { const auto it{IR::Block::InstructionList::s_iterator_to(inst)}; IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; @@ -505,19 +520,6 @@ void PatchTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_ ir.FPMul(ir.ConvertSToF(32, 32, ir.BitCast(w)), max_value)); inst.ReplaceUsesWith(converted); } - -void PatchSmallFloatImageWrite(IR::Block& block, IR::Inst& inst) { - IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; - - const IR::Value old_value{inst.Arg(2)}; - const IR::F32 x(ir.BitCast(IR::U32(ir.CompositeExtract(old_value, 0)))); - const IR::F32 y(ir.BitCast(IR::U32(ir.CompositeExtract(old_value, 1)))); - const IR::F32 z(ir.BitCast(IR::U32(ir.CompositeExtract(old_value, 2)))); - const IR::F32 w(ir.BitCast(IR::U32(ir.CompositeExtract(old_value, 3)))); - const IR::Value converted = ir.CompositeConstruct(x, y, z, w); - inst.SetArg(2, converted); -} - } // Anonymous namespace void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo& host_info) { @@ -549,9 +551,6 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo inst->ReplaceOpcode(IndexedInstruction(*inst)); const auto& cbuf{texture_inst.cbuf}; - const bool is_float_write{!host_info.support_ufloat_write_as_uint && - inst->GetOpcode() == IR::Opcode::ImageWrite && - TexturePixelFormatIsFloat(env, cbuf)}; auto flags{inst->Flags()}; bool is_multisample{false}; switch (inst->GetOpcode()) { @@ -608,11 +607,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 bool is_integer{IsTexturePixelFormatInteger(env, cbuf)}; if (flags.type == TextureType::Buffer) { index = descriptors.Add(ImageBufferDescriptor{ .format = flags.image_format, .is_written = is_written, .is_read = is_read, + .is_integer = is_integer, .cbuf_index = cbuf.index, .cbuf_offset = cbuf.offset, .count = cbuf.count, @@ -624,7 +625,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo .format = flags.image_format, .is_written = is_written, .is_read = is_read, - .is_float = is_float_write, + .is_integer = is_integer, .cbuf_index = cbuf.index, .cbuf_offset = cbuf.offset, .count = cbuf.count, @@ -680,14 +681,10 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo if (!host_info.support_snorm_render_buffer && inst->GetOpcode() == IR::Opcode::ImageFetch && flags.type == TextureType::Buffer) { const auto pixel_format = ReadTexturePixelFormat(env, cbuf); - if (pixel_format != TexturePixelFormat::OTHER) { + if (IsPixelFormatSNorm(pixel_format)) { PatchTexelFetch(*texture_inst.block, *texture_inst.inst, pixel_format); } } - - if (is_float_write) { - PatchSmallFloatImageWrite(*texture_inst.block, *inst); - } } } diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index fad65ab73..faa5157c6 100755 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h @@ -35,15 +35,109 @@ enum class TextureType : u32 { }; constexpr u32 NUM_TEXTURE_TYPES = 9; -enum class TexturePixelFormat : u32 { +enum class TexturePixelFormat { + A8B8G8R8_UNORM, A8B8G8R8_SNORM, + A8B8G8R8_SINT, + A8B8G8R8_UINT, + R5G6B5_UNORM, + B5G6R5_UNORM, + A1R5G5B5_UNORM, + A2B10G10R10_UNORM, + A2B10G10R10_UINT, + A2R10G10B10_UNORM, + A1B5G5R5_UNORM, + A5B5G5R1_UNORM, + R8_UNORM, R8_SNORM, - R8G8_SNORM, + R8_SINT, + R8_UINT, + R16G16B16A16_FLOAT, + R16G16B16A16_UNORM, R16G16B16A16_SNORM, - R16G16_SNORM, - R16_SNORM, + R16G16B16A16_SINT, + R16G16B16A16_UINT, B10G11R11_FLOAT, - OTHER + R32G32B32A32_UINT, + BC1_RGBA_UNORM, + BC2_UNORM, + BC3_UNORM, + BC4_UNORM, + BC4_SNORM, + BC5_UNORM, + BC5_SNORM, + BC7_UNORM, + BC6H_UFLOAT, + BC6H_SFLOAT, + ASTC_2D_4X4_UNORM, + B8G8R8A8_UNORM, + R32G32B32A32_FLOAT, + R32G32B32A32_SINT, + R32G32_FLOAT, + R32G32_SINT, + R32_FLOAT, + R16_FLOAT, + R16_UNORM, + R16_SNORM, + R16_UINT, + R16_SINT, + R16G16_UNORM, + R16G16_FLOAT, + R16G16_UINT, + R16G16_SINT, + R16G16_SNORM, + R32G32B32_FLOAT, + A8B8G8R8_SRGB, + R8G8_UNORM, + R8G8_SNORM, + R8G8_SINT, + R8G8_UINT, + R32G32_UINT, + R16G16B16X16_FLOAT, + R32_UINT, + R32_SINT, + ASTC_2D_8X8_UNORM, + ASTC_2D_8X5_UNORM, + ASTC_2D_5X4_UNORM, + B8G8R8A8_SRGB, + BC1_RGBA_SRGB, + BC2_SRGB, + BC3_SRGB, + BC7_SRGB, + A4B4G4R4_UNORM, + G4R4_UNORM, + ASTC_2D_4X4_SRGB, + ASTC_2D_8X8_SRGB, + ASTC_2D_8X5_SRGB, + ASTC_2D_5X4_SRGB, + ASTC_2D_5X5_UNORM, + ASTC_2D_5X5_SRGB, + ASTC_2D_10X8_UNORM, + ASTC_2D_10X8_SRGB, + ASTC_2D_6X6_UNORM, + ASTC_2D_6X6_SRGB, + ASTC_2D_10X6_UNORM, + ASTC_2D_10X6_SRGB, + ASTC_2D_10X5_UNORM, + ASTC_2D_10X5_SRGB, + ASTC_2D_10X10_UNORM, + ASTC_2D_10X10_SRGB, + ASTC_2D_12X10_UNORM, + ASTC_2D_12X10_SRGB, + ASTC_2D_12X12_UNORM, + ASTC_2D_12X12_SRGB, + ASTC_2D_8X6_UNORM, + ASTC_2D_8X6_SRGB, + ASTC_2D_6X5_UNORM, + ASTC_2D_6X5_SRGB, + E5B9G9R9_FLOAT, + D32_FLOAT, + D16_UNORM, + X8_D24_UNORM, + S8_UINT, + D24_UNORM_S8_UINT, + S8_UINT_D24_UNORM, + D32_FLOAT_S8_UINT, }; enum class ImageFormat : u32 { @@ -98,6 +192,7 @@ struct ImageBufferDescriptor { ImageFormat format; bool is_written; bool is_read; + bool is_integer; u32 cbuf_index; u32 cbuf_offset; u32 count; @@ -130,7 +225,7 @@ struct ImageDescriptor { ImageFormat format; bool is_written; bool is_read; - bool is_float; + bool is_integer; u32 cbuf_index; u32 cbuf_offset; u32 count; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 83c0d6cae..f62b94cf6 100755 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -51,7 +51,7 @@ using VideoCommon::LoadPipelines; using VideoCommon::SerializePipeline; using Context = ShaderContext::Context; -constexpr u32 CACHE_VERSION = 9; +constexpr u32 CACHE_VERSION = 10; template auto MakeSpan(Container& container) { @@ -245,7 +245,6 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo .min_ssbo_alignment = static_cast(device.GetShaderStorageBufferAlignment()), .support_geometry_shader_passthrough = device.HasGeometryShaderPassthrough(), .support_conditional_barrier = device.SupportsConditionalBarriers(), - .support_ufloat_write_as_uint = true, } { if (use_asynchronous_shaders) { workers = CreateWorkers(); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 6a4f52b14..cf137f6a4 100755 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -54,7 +54,7 @@ using VideoCommon::FileEnvironment; using VideoCommon::GenericEnvironment; using VideoCommon::GraphicsEnvironment; -constexpr u32 CACHE_VERSION = 10; +constexpr u32 CACHE_VERSION = 11; constexpr std::array VULKAN_CACHE_MAGIC_NUMBER{'y', 'u', 'z', 'u', 'v', 'k', 'c', 'h'}; template @@ -388,9 +388,6 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device .min_ssbo_alignment = static_cast(device.GetStorageBufferAlignment()), .support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(), .support_conditional_barrier = device.SupportsConditionalBarriers(), - .support_ufloat_write_as_uint = driver_id != VK_DRIVER_ID_QUALCOMM_PROPRIETARY && - driver_id != VK_DRIVER_ID_MESA_TURNIP && - driver_id != VK_DRIVER_ID_ARM_PROPRIETARY, }; if (device.GetMaxVertexInputAttributes() < Maxwell::NumVertexAttributes) { diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index 8bee3cf84..12002a4ac 100755 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp @@ -62,25 +62,9 @@ static Shader::TextureType ConvertTextureType(const Tegra::Texture::TICEntry& en } static Shader::TexturePixelFormat ConvertTexturePixelFormat(const Tegra::Texture::TICEntry& entry) { - switch (PixelFormatFromTextureInfo(entry.format, entry.r_type, entry.g_type, entry.b_type, - entry.a_type, entry.srgb_conversion)) { - case VideoCore::Surface::PixelFormat::A8B8G8R8_SNORM: - return Shader::TexturePixelFormat::A8B8G8R8_SNORM; - case VideoCore::Surface::PixelFormat::R8_SNORM: - return Shader::TexturePixelFormat::R8_SNORM; - case VideoCore::Surface::PixelFormat::R8G8_SNORM: - return Shader::TexturePixelFormat::R8G8_SNORM; - case VideoCore::Surface::PixelFormat::R16G16B16A16_SNORM: - return Shader::TexturePixelFormat::R16G16B16A16_SNORM; - case VideoCore::Surface::PixelFormat::R16G16_SNORM: - return Shader::TexturePixelFormat::R16G16_SNORM; - case VideoCore::Surface::PixelFormat::R16_SNORM: - return Shader::TexturePixelFormat::R16_SNORM; - case VideoCore::Surface::PixelFormat::B10G11R11_FLOAT: - return Shader::TexturePixelFormat::B10G11R11_FLOAT; - default: - return Shader::TexturePixelFormat::OTHER; - } + return static_cast( + PixelFormatFromTextureInfo(entry.format, entry.r_type, entry.g_type, entry.b_type, + entry.a_type, entry.srgb_conversion)); } static std::string_view StageToPrefix(Shader::Stage stage) { @@ -400,6 +384,11 @@ Shader::TexturePixelFormat GraphicsEnvironment::ReadTexturePixelFormat(u32 handl return result; } +bool GraphicsEnvironment::IsTexturePixelFormatInteger(u32 handle) { + return VideoCore::Surface::IsPixelFormatInteger( + static_cast(ReadTexturePixelFormat(handle))); +} + u32 GraphicsEnvironment::ReadViewportTransformState() { const auto& regs{maxwell3d->regs}; viewport_transform_state = regs.viewport_scale_offset_enabled; @@ -450,6 +439,11 @@ Shader::TexturePixelFormat ComputeEnvironment::ReadTexturePixelFormat(u32 handle return result; } +bool ComputeEnvironment::IsTexturePixelFormatInteger(u32 handle) { + return VideoCore::Surface::IsPixelFormatInteger( + static_cast(ReadTexturePixelFormat(handle))); +} + u32 ComputeEnvironment::ReadViewportTransformState() { return viewport_transform_state; } @@ -553,6 +547,11 @@ Shader::TexturePixelFormat FileEnvironment::ReadTexturePixelFormat(u32 handle) { return it->second; } +bool FileEnvironment::IsTexturePixelFormatInteger(u32 handle) { + return VideoCore::Surface::IsPixelFormatInteger( + static_cast(ReadTexturePixelFormat(handle))); +} + u32 FileEnvironment::ReadViewportTransformState() { return viewport_transform_state; } diff --git a/src/video_core/shader_environment.h b/src/video_core/shader_environment.h index 06e7b4b09..ba773ff1f 100755 --- a/src/video_core/shader_environment.h +++ b/src/video_core/shader_environment.h @@ -115,6 +115,8 @@ public: Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override; + bool IsTexturePixelFormatInteger(u32 handle) override; + u32 ReadViewportTransformState() override; std::optional GetReplaceConstBuffer(u32 bank, u32 offset) override; @@ -139,6 +141,8 @@ public: Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override; + bool IsTexturePixelFormatInteger(u32 handle) override; + u32 ReadViewportTransformState() override; std::optional GetReplaceConstBuffer( @@ -171,6 +175,8 @@ public: [[nodiscard]] Shader::TexturePixelFormat ReadTexturePixelFormat(u32 handle) override; + [[nodiscard]] bool IsTexturePixelFormatInteger(u32 handle) override; + [[nodiscard]] u32 ReadViewportTransformState() override; [[nodiscard]] u32 LocalMemorySize() const override;