summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2021-08-01 23:57:45 +0200
committerFernando Sahmkow <fsahmkow27@gmail.com>2021-11-16 22:11:29 +0100
commite66d5b88a6f1c2d85c5cd8e351c6ed52c96a0ecf (patch)
tree0107548906df0b9d42e89451489be6a54ed71bf3 /src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
parentshader: Properly blacklist and scale image loads (diff)
downloadyuzu-e66d5b88a6f1c2d85c5cd8e351c6ed52c96a0ecf.tar
yuzu-e66d5b88a6f1c2d85c5cd8e351c6ed52c96a0ecf.tar.gz
yuzu-e66d5b88a6f1c2d85c5cd8e351c6ed52c96a0ecf.tar.bz2
yuzu-e66d5b88a6f1c2d85c5cd8e351c6ed52c96a0ecf.tar.lz
yuzu-e66d5b88a6f1c2d85c5cd8e351c6ed52c96a0ecf.tar.xz
yuzu-e66d5b88a6f1c2d85c5cd8e351c6ed52c96a0ecf.tar.zst
yuzu-e66d5b88a6f1c2d85c5cd8e351c6ed52c96a0ecf.zip
Diffstat (limited to '')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_image.cpp74
1 files changed, 53 insertions, 21 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
index 7d7c0627e..519ce8b9b 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_image.cpp
@@ -224,6 +224,40 @@ Id Emit(MethodPtrType sparse_ptr, MethodPtrType non_sparse_ptr, EmitContext& ctx
Decorate(ctx, inst, sample);
return ctx.OpCompositeExtract(result_type, sample, 1U);
}
+
+Id IsScaled(EmitContext& ctx, const IR::Value& index, Id member_index, u32 base_index) {
+ const Id push_constant_u32{ctx.TypePointer(spv::StorageClass::PushConstant, ctx.U32[1])};
+ 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() + base_index};
+ 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 {
+ Id index_value{ctx.Def(index)};
+ if (base_index != 0) {
+ index_value = ctx.OpIAdd(ctx.U32[1], index_value, ctx.Const(base_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);
+}
+
+Id BitTest(EmitContext& ctx, Id mask, Id bit) {
+ const Id shifted{ctx.OpShiftRightLogical(ctx.U32[1], mask, bit)};
+ const Id bit_value{ctx.OpBitwiseAnd(ctx.U32[1], shifted, ctx.Const(1u))};
+ return ctx.OpINotEqual(ctx.U1, bit_value, ctx.u32_zero_value);
+}
} // Anonymous namespace
Id EmitBindlessImageSampleImplicitLod(EmitContext&) {
@@ -471,29 +505,27 @@ void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id
}
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);
+ if (ctx.profile.unified_descriptor_binding) {
+ const Id member_index{ctx.Const(ctx.rescaling_textures_member_index)};
+ return IsScaled(ctx, index, member_index, ctx.texture_rescaling_index);
} 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));
+ const Id composite{ctx.OpLoad(ctx.F32[4], ctx.rescaling_uniform_constant)};
+ const Id mask_f32{ctx.OpCompositeExtract(ctx.F32[1], composite, 0u)};
+ const Id mask{ctx.OpBitcast(ctx.U32[1], mask_f32)};
+ return BitTest(ctx, mask, ctx.Def(index));
+ }
+}
+
+Id EmitIsImageScaled(EmitContext& ctx, const IR::Value& index) {
+ if (ctx.profile.unified_descriptor_binding) {
+ const Id member_index{ctx.Const(ctx.rescaling_images_member_index)};
+ return IsScaled(ctx, index, member_index, ctx.image_rescaling_index);
+ } else {
+ const Id composite{ctx.OpLoad(ctx.F32[4], ctx.rescaling_uniform_constant)};
+ const Id mask_f32{ctx.OpCompositeExtract(ctx.F32[1], composite, 1u)};
+ const Id mask{ctx.OpBitcast(ctx.U32[1], mask_f32)};
+ return BitTest(ctx, mask, ctx.Def(index));
}
- return ctx.OpINotEqual(ctx.U1, bit, ctx.u32_zero_value);
}
} // namespace Shader::Backend::SPIRV