diff options
Diffstat (limited to 'src/shader_recompiler/backend/spirv/emit_spirv_image.cpp')
-rw-r--r-- | src/shader_recompiler/backend/spirv/emit_spirv_image.cpp | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp index 2f925cc3e..7d7c0627e 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp @@ -470,8 +470,30 @@ void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id ctx.OpImageWrite(Image(ctx, index, info), coords, color); } -Id EmitIsTextureScaled([[maybe_unused]] EmitContext& ctx, [[maybe_unused]] const IR::Value& index) { - return ctx.false_value; +Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index) { + const Id push_constant_u32{ctx.TypePointer(spv::StorageClass::PushConstant, ctx.U32[1])}; + const Id member_index{ctx.Const(ctx.rescaling_textures_member_index)}; + Id bit{}; + if (index.IsImmediate()) { + // Use BitwiseAnd instead of BitfieldExtract for better codegen on Nvidia OpenGL. + // LOP32I.NZ is used to set the predicate rather than BFE+ISETP. + const u32 index_value{index.U32()}; + const Id word_index{ctx.Const(index_value / 32)}; + const Id bit_index_mask{ctx.Const(1u << (index_value % 32))}; + const Id pointer{ctx.OpAccessChain(push_constant_u32, ctx.rescaling_push_constants, + member_index, word_index)}; + const Id word{ctx.OpLoad(ctx.U32[1], pointer)}; + bit = ctx.OpBitwiseAnd(ctx.U32[1], word, bit_index_mask); + } else { + const Id index_value{ctx.Def(index)}; + const Id word_index{ctx.OpShiftRightArithmetic(ctx.U32[1], index_value, ctx.Const(5u))}; + const Id pointer{ctx.OpAccessChain(push_constant_u32, ctx.rescaling_push_constants, + member_index, word_index)}; + const Id word{ctx.OpLoad(ctx.U32[1], pointer)}; + const Id bit_index{ctx.OpBitwiseAnd(ctx.U32[1], index_value, ctx.Const(31u))}; + bit = ctx.OpBitFieldUExtract(ctx.U32[1], index_value, bit_index, ctx.Const(1u)); + } + return ctx.OpINotEqual(ctx.U1, bit, ctx.u32_zero_value); } } // namespace Shader::Backend::SPIRV |