From 360e897ccd53bf863cea1ad6184d35e9b6ffbf40 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 18 Jul 2021 23:06:12 +0200 Subject: ShaderDecompiler: Add initial support for rescaling. --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 72 +++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/shader_recompiler/ir_opt/rescaling_pass.cpp (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp new file mode 100644 index 000000000..d3ae3f159 --- /dev/null +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -0,0 +1,72 @@ +// Copyright 2021 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/alignment.h" +#include "shader_recompiler/environment.h" +#include "shader_recompiler/frontend/ir/modifiers.h" +#include "shader_recompiler/frontend/ir/program.h" +#include "shader_recompiler/frontend/ir/value.h" +#include "shader_recompiler/ir_opt/passes.h" +#include "shader_recompiler/shader_info.h" + +namespace Shader::Optimization { +namespace { + +void PatchFragCoord(IR::Inst& inst) { + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + const IR::F32 inv_resolution_factor = IR::F32{Settings::values.resolution_info.down_factor}; + const IR::F32 new_get_attribute = ir.GetAttribute(inst.Arg(0).Attribute()); + const IR::F32 mul = ir.FMul(new_get_attribute, inv_resolution_factor); + const IR::U1 should_rescale = IR::U1{true}; + const IR::F32 selection = ir.Select(should_rescale, mul, new_get_attribute); + inst.ReplaceUsesWith(selection); +} + +void Visit(Info& info, IR::Inst& inst) { + info.requires_rescaling_uniform = false; + switch (inst.GetOpcode()) { + case IR::Opcode::GetAttribute: { + conast auto attrib = inst.Arg(0).Attribute(); + const bool is_frag = + attrib == IR::Attribute::PositionX || attrib == IR::Attribute::PositionY; + const bool must_path = is_frag && program.stage == Stage::Fragment; + if (must_path) { + PatchFragCoord(inst); + info.requires_rescaling_uniform = true; + } + break; + } + case IR::Opcode::ImageQueryDimensions: { + info.requires_rescaling_uniform |= true; + break; + } + case IR::Opcode::ImageFetch: { + info.requires_rescaling_uniform |= true; + break; + } + case IR::Opcode::ImageRead: { + info.requires_rescaling_uniform |= true; + break; + } + case IR::Opcode::ImageWrite: { + info.requires_rescaling_uniform |= true; + break; + } + default: + break; + } +} + +} // namespace + +void RescalingPass(Environment& env, IR::Program& program) { + Info& info{program.info}; + for (IR::Block* const block : program.post_order_blocks) { + for (IR::Inst& inst : block->Instructions()) { + Visit(info, inst); + } + } +} + +} // namespace Shader::Optimization -- cgit v1.2.3 From 1672e9ba092f6bc268ece7619c4bae793c00c580 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Wed, 21 Jul 2021 22:25:34 -0300 Subject: shader: Fix resolution scaling pass --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 60 +++++++++++-------------- 1 file changed, 26 insertions(+), 34 deletions(-) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index d3ae3f159..293593c78 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -3,7 +3,9 @@ // Refer to the license.txt file included. #include "common/alignment.h" +#include "common/settings.h" #include "shader_recompiler/environment.h" +#include "shader_recompiler/frontend/ir/ir_emitter.h" #include "shader_recompiler/frontend/ir/modifiers.h" #include "shader_recompiler/frontend/ir/program.h" #include "shader_recompiler/frontend/ir/value.h" @@ -12,59 +14,49 @@ namespace Shader::Optimization { namespace { - -void PatchFragCoord(IR::Inst& inst) { +void PatchFragCoord(IR::Block& block, IR::Inst& inst) { IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; - const IR::F32 inv_resolution_factor = IR::F32{Settings::values.resolution_info.down_factor}; - const IR::F32 new_get_attribute = ir.GetAttribute(inst.Arg(0).Attribute()); - const IR::F32 mul = ir.FMul(new_get_attribute, inv_resolution_factor); - const IR::U1 should_rescale = IR::U1{true}; - const IR::F32 selection = ir.Select(should_rescale, mul, new_get_attribute); - inst.ReplaceUsesWith(selection); + const IR::F32 down_factor{ir.ResolutionDownFactor()}; + const IR::F32 frag_coord{&inst}; + const IR::F32 downscaled_frag_coord{ir.FPMul(frag_coord, down_factor)}; + inst.ReplaceUsesWith(downscaled_frag_coord); } -void Visit(Info& info, IR::Inst& inst) { - info.requires_rescaling_uniform = false; +void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { + const bool is_fragment_shader{program.stage == Stage::Fragment}; switch (inst.GetOpcode()) { case IR::Opcode::GetAttribute: { - conast auto attrib = inst.Arg(0).Attribute(); - const bool is_frag = - attrib == IR::Attribute::PositionX || attrib == IR::Attribute::PositionY; - const bool must_path = is_frag && program.stage == Stage::Fragment; - if (must_path) { - PatchFragCoord(inst); - info.requires_rescaling_uniform = true; + const IR::Attribute attr{inst.Arg(0).Attribute()}; + switch (attr) { + case IR::Attribute::PositionX: + case IR::Attribute::PositionY: + if (is_fragment_shader) { + PatchFragCoord(block, inst); + } + break; + default: + break; } break; } - case IR::Opcode::ImageQueryDimensions: { - info.requires_rescaling_uniform |= true; + case IR::Opcode::ImageQueryDimensions: break; - } - case IR::Opcode::ImageFetch: { - info.requires_rescaling_uniform |= true; + case IR::Opcode::ImageFetch: break; - } - case IR::Opcode::ImageRead: { - info.requires_rescaling_uniform |= true; + case IR::Opcode::ImageRead: break; - } - case IR::Opcode::ImageWrite: { - info.requires_rescaling_uniform |= true; + case IR::Opcode::ImageWrite: break; - } default: break; } } +} // Anonymous namespace -} // namespace - -void RescalingPass(Environment& env, IR::Program& program) { - Info& info{program.info}; +void RescalingPass(IR::Program& program) { for (IR::Block* const block : program.post_order_blocks) { for (IR::Inst& inst : block->Instructions()) { - Visit(info, inst); + Visit(program, *block, inst); } } } -- cgit v1.2.3 From e580299467a8aa7f56e8b66a63112dc06c870b15 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 22 Jul 2021 04:29:00 -0300 Subject: shader: Fix rescaling pass --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index 293593c78..f8d04b6e3 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -17,7 +17,7 @@ namespace { void PatchFragCoord(IR::Block& block, IR::Inst& inst) { IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; const IR::F32 down_factor{ir.ResolutionDownFactor()}; - const IR::F32 frag_coord{&inst}; + const IR::F32 frag_coord{ir.GetAttribute(inst.Arg(0).Attribute())}; const IR::F32 downscaled_frag_coord{ir.FPMul(frag_coord, down_factor)}; inst.ReplaceUsesWith(downscaled_frag_coord); } -- cgit v1.2.3 From 01379c5e3cd1181c7c7d37a672364fbcad627fb0 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 25 Jul 2021 22:20:56 -0300 Subject: shader/rescaling_pass: Patch more instructions --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 105 +++++++++++++++++++++++- 1 file changed, 101 insertions(+), 4 deletions(-) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index f8d04b6e3..d5b98ae6e 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -22,6 +22,105 @@ void PatchFragCoord(IR::Block& block, IR::Inst& inst) { inst.ReplaceUsesWith(downscaled_frag_coord); } +[[nodiscard]] IR::U32 Scale(IR::IREmitter& ir, const IR::U1& is_scaled, const IR::U32& value) { + IR::U32 scaled_value{value}; + bool changed{}; + if (const u32 up_scale = Settings::values.resolution_info.up_scale; up_scale != 1) { + scaled_value = ir.IMul(value, ir.Imm32(up_scale)); + changed = true; + } + if (const u32 down_shift = Settings::values.resolution_info.down_shift; down_shift != 0) { + scaled_value = ir.ShiftRightArithmetic(value, ir.Imm32(down_shift)); + changed = true; + } + if (changed) { + return IR::U32{ir.Select(is_scaled, scaled_value, value)}; + } else { + return value; + } +} + +[[nodiscard]] IR::U32 DownScale(IR::IREmitter& ir, IR::U32 value) { + if (const u32 down_shift = Settings::values.resolution_info.down_shift; down_shift != 0) { + value = ir.ShiftLeftLogical(value, ir.Imm32(down_shift)); + } + if (const u32 up_scale = Settings::values.resolution_info.up_scale; up_scale != 1) { + value = ir.IDiv(value, ir.Imm32(up_scale)); + } + return value; +} + +void PatchImageQueryDimensions(IR::Block& block, IR::Inst& inst) { + const auto it{IR::Block::InstructionList::s_iterator_to(inst)}; + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + const auto info{inst.Flags()}; + switch (info.type) { + case TextureType::Color1D: + case TextureType::ColorArray1D: { + const IR::Value new_inst{&*block.PrependNewInst(it, inst)}; + const IR::U32 width{DownScale(ir, IR::U32{ir.CompositeExtract(new_inst, 0)})}; + const IR::Value replacement{ir.CompositeConstruct(width, ir.CompositeExtract(new_inst, 1), + ir.CompositeExtract(new_inst, 2), + ir.CompositeExtract(new_inst, 3))}; + inst.ReplaceUsesWith(replacement); + break; + } + case TextureType::Color2D: + case TextureType::ColorArray2D: { + const IR::Value new_inst{&*block.PrependNewInst(it, inst)}; + const IR::U32 width{DownScale(ir, IR::U32{ir.CompositeExtract(new_inst, 0)})}; + const IR::U32 height{DownScale(ir, IR::U32{ir.CompositeExtract(new_inst, 1)})}; + const IR::Value replacement{ir.CompositeConstruct( + width, height, ir.CompositeExtract(new_inst, 2), ir.CompositeExtract(new_inst, 3))}; + inst.ReplaceUsesWith(replacement); + break; + } + case TextureType::Color3D: + case TextureType::ColorCube: + case TextureType::ColorArrayCube: + case TextureType::Buffer: + // Nothing to patch here + break; + } +} + +void PatchImageFetch(IR::Block& block, IR::Inst& inst) { + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + const auto info{inst.Flags()}; + const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))}; + const IR::Value coord{inst.Arg(1)}; + switch (info.type) { + case TextureType::Color1D: + inst.SetArg(1, Scale(ir, is_scaled, IR::U32{coord})); + break; + case TextureType::ColorArray1D: { + const IR::U32 x{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)})}; + const IR::U32 y{ir.CompositeExtract(coord, 1)}; + inst.SetArg(1, ir.CompositeConstruct(x, y)); + break; + } + case TextureType::Color2D: { + const IR::U32 x{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)})}; + const IR::U32 y{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)})}; + inst.SetArg(1, ir.CompositeConstruct(x, y)); + break; + } + case TextureType::ColorArray2D: { + const IR::U32 x{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)})}; + const IR::U32 y{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)})}; + const IR::U32 z{ir.CompositeExtract(coord, 2)}; + inst.SetArg(1, ir.CompositeConstruct(x, y, z)); + break; + } + case TextureType::Color3D: + case TextureType::ColorCube: + case TextureType::ColorArrayCube: + case TextureType::Buffer: + // Nothing to patch here + break; + } +} + void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { const bool is_fragment_shader{program.stage == Stage::Fragment}; switch (inst.GetOpcode()) { @@ -40,12 +139,10 @@ void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { break; } case IR::Opcode::ImageQueryDimensions: + PatchImageQueryDimensions(block, inst); break; case IR::Opcode::ImageFetch: - break; - case IR::Opcode::ImageRead: - break; - case IR::Opcode::ImageWrite: + PatchImageFetch(block, inst); break; default: break; -- cgit v1.2.3 From fc9bb3c3fed4721b06bda46deea3770e5285b104 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 1 Aug 2021 02:26:02 -0300 Subject: shader: Properly blacklist and scale image loads --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index d5b98ae6e..86c8f0c69 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -84,10 +84,8 @@ void PatchImageQueryDimensions(IR::Block& block, IR::Inst& inst) { } } -void PatchImageFetch(IR::Block& block, IR::Inst& inst) { - IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; +void ScaleIntegerCoord(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_scaled) { const auto info{inst.Flags()}; - const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))}; const IR::Value coord{inst.Arg(1)}; switch (info.type) { case TextureType::Color1D: @@ -121,6 +119,21 @@ void PatchImageFetch(IR::Block& block, IR::Inst& inst) { } } +void PatchImageFetch(IR::Block& block, IR::Inst& inst) { + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + const auto info{inst.Flags()}; + const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))}; + ScaleIntegerCoord(ir, inst, is_scaled); +} + +void PatchImageRead(IR::Block& block, IR::Inst& inst) { + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + const auto info{inst.Flags()}; + // TODO: Scale conditionally + const IR::U1 is_scaled{IR::Value{true}}; + ScaleIntegerCoord(ir, inst, is_scaled); +} + void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { const bool is_fragment_shader{program.stage == Stage::Fragment}; switch (inst.GetOpcode()) { @@ -144,6 +157,9 @@ void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { case IR::Opcode::ImageFetch: PatchImageFetch(block, inst); break; + case IR::Opcode::ImageRead: + PatchImageRead(block, inst); + break; default: break; } -- cgit v1.2.3 From e66d5b88a6f1c2d85c5cd8e351c6ed52c96a0ecf Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Sun, 1 Aug 2021 18:57:45 -0300 Subject: shader: Properly scale image reads and add GL SPIR-V support Thanks for everything! --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index 86c8f0c69..2af12fc07 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -129,8 +129,7 @@ void PatchImageFetch(IR::Block& block, IR::Inst& inst) { void PatchImageRead(IR::Block& block, IR::Inst& inst) { IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; const auto info{inst.Flags()}; - // TODO: Scale conditionally - const IR::U1 is_scaled{IR::Value{true}}; + const IR::U1 is_scaled{ir.IsImageScaled(ir.Imm32(info.descriptor_index))}; ScaleIntegerCoord(ir, inst, is_scaled); } -- cgit v1.2.3 From 8f78444de35bdbdc83a709b8a822d66018bb9852 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 2 Aug 2021 01:03:15 +0200 Subject: shader: Fix TextureSize check on rescaling. --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 48 +++++++++++-------------- 1 file changed, 21 insertions(+), 27 deletions(-) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index 2af12fc07..b94273aa5 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -26,11 +26,11 @@ void PatchFragCoord(IR::Block& block, IR::Inst& inst) { IR::U32 scaled_value{value}; bool changed{}; if (const u32 up_scale = Settings::values.resolution_info.up_scale; up_scale != 1) { - scaled_value = ir.IMul(value, ir.Imm32(up_scale)); + scaled_value = ir.IMul(scaled_value, ir.Imm32(up_scale)); changed = true; } if (const u32 down_shift = Settings::values.resolution_info.down_shift; down_shift != 0) { - scaled_value = ir.ShiftRightArithmetic(value, ir.Imm32(down_shift)); + scaled_value = ir.ShiftRightArithmetic(scaled_value, ir.Imm32(down_shift)); changed = true; } if (changed) { @@ -40,41 +40,42 @@ void PatchFragCoord(IR::Block& block, IR::Inst& inst) { } } -[[nodiscard]] IR::U32 DownScale(IR::IREmitter& ir, IR::U32 value) { +[[nodiscard]] IR::U32 DownScale(IR::IREmitter& ir, const IR::U1& is_scaled, IR::U32 value) { + IR::U32 scaled_value{value}; + bool changed{}; if (const u32 down_shift = Settings::values.resolution_info.down_shift; down_shift != 0) { - value = ir.ShiftLeftLogical(value, ir.Imm32(down_shift)); + scaled_value = ir.ShiftLeftLogical(scaled_value, ir.Imm32(down_shift)); + changed = true; } if (const u32 up_scale = Settings::values.resolution_info.up_scale; up_scale != 1) { - value = ir.IDiv(value, ir.Imm32(up_scale)); + scaled_value = ir.IDiv(scaled_value, ir.Imm32(up_scale)); + changed = true; + } + if (changed) { + return IR::U32{ir.Select(is_scaled, scaled_value, value)}; + } else { + return value; } - return value; } void PatchImageQueryDimensions(IR::Block& block, IR::Inst& inst) { const auto it{IR::Block::InstructionList::s_iterator_to(inst)}; IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; const auto info{inst.Flags()}; + const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))}; switch (info.type) { - case TextureType::Color1D: - case TextureType::ColorArray1D: { - const IR::Value new_inst{&*block.PrependNewInst(it, inst)}; - const IR::U32 width{DownScale(ir, IR::U32{ir.CompositeExtract(new_inst, 0)})}; - const IR::Value replacement{ir.CompositeConstruct(width, ir.CompositeExtract(new_inst, 1), - ir.CompositeExtract(new_inst, 2), - ir.CompositeExtract(new_inst, 3))}; - inst.ReplaceUsesWith(replacement); - break; - } case TextureType::Color2D: case TextureType::ColorArray2D: { const IR::Value new_inst{&*block.PrependNewInst(it, inst)}; - const IR::U32 width{DownScale(ir, IR::U32{ir.CompositeExtract(new_inst, 0)})}; - const IR::U32 height{DownScale(ir, IR::U32{ir.CompositeExtract(new_inst, 1)})}; + const IR::U32 width{DownScale(ir, is_scaled, IR::U32{ir.CompositeExtract(new_inst, 0)})}; + const IR::U32 height{DownScale(ir, is_scaled, IR::U32{ir.CompositeExtract(new_inst, 1)})}; const IR::Value replacement{ir.CompositeConstruct( width, height, ir.CompositeExtract(new_inst, 2), ir.CompositeExtract(new_inst, 3))}; inst.ReplaceUsesWith(replacement); break; } + case TextureType::Color1D: + case TextureType::ColorArray1D: case TextureType::Color3D: case TextureType::ColorCube: case TextureType::ColorArrayCube: @@ -88,15 +89,6 @@ void ScaleIntegerCoord(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_scale const auto info{inst.Flags()}; const IR::Value coord{inst.Arg(1)}; switch (info.type) { - case TextureType::Color1D: - inst.SetArg(1, Scale(ir, is_scaled, IR::U32{coord})); - break; - case TextureType::ColorArray1D: { - const IR::U32 x{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)})}; - const IR::U32 y{ir.CompositeExtract(coord, 1)}; - inst.SetArg(1, ir.CompositeConstruct(x, y)); - break; - } case TextureType::Color2D: { const IR::U32 x{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)})}; const IR::U32 y{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)})}; @@ -110,6 +102,8 @@ void ScaleIntegerCoord(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_scale inst.SetArg(1, ir.CompositeConstruct(x, y, z)); break; } + case TextureType::Color1D: + case TextureType::ColorArray1D: case TextureType::Color3D: case TextureType::ColorCube: case TextureType::ColorArrayCube: -- cgit v1.2.3 From dfa82915262ca26d0884528b7bdae791554332ca Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 7 Aug 2021 02:59:05 +0200 Subject: RescalingPass: Agregate pixels on texelFetch while on Fragment Shader --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 100 +++++++++++++++++++++++- 1 file changed, 97 insertions(+), 3 deletions(-) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index b94273aa5..71c9d9e6f 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -40,6 +40,22 @@ void PatchFragCoord(IR::Block& block, IR::Inst& inst) { } } +[[nodiscard]] IR::U32 SubScale(IR::IREmitter& ir, const IR::U1& is_scaled, const IR::U32& value, + const IR::Attribute attrib) { + if (Settings::values.resolution_info.active) { + const IR::F32 opt1{ir.Imm32(Settings::values.resolution_info.up_factor)}; + const IR::F32 base{ir.FPMul(ir.ConvertUToF(32, 32, value), opt1)}; + const IR::F32 frag_coord{ir.GetAttribute(attrib)}; + const IR::F32 opt2{ir.Imm32(Settings::values.resolution_info.down_factor)}; + const IR::F32 floor{ir.FPMul(opt1, ir.FPFloor(ir.FPMul(frag_coord, opt2)))}; + const IR::U32 deviation{ + ir.ConvertFToU(32, ir.FPAdd(base, ir.FPAdd(frag_coord, ir.FPNeg(floor))))}; + return IR::U32{ir.Select(is_scaled, deviation, value)}; + } else { + return value; + } +} + [[nodiscard]] IR::U32 DownScale(IR::IREmitter& ir, const IR::U1& is_scaled, IR::U32 value) { IR::U32 scaled_value{value}; bool changed{}; @@ -113,6 +129,74 @@ void ScaleIntegerCoord(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_scale } } +void SubScaleImageFetch(IR::Block& block, IR::Inst& inst) { + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + const auto info{inst.Flags()}; + const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))}; + const IR::Value coord{inst.Arg(1)}; + switch (info.type) { + case TextureType::Color2D: { + const IR::U32 x{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)}, + IR::Attribute::PositionX)}; + const IR::U32 y{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)}, + IR::Attribute::PositionY)}; + inst.SetArg(1, ir.CompositeConstruct(x, y)); + break; + } + case TextureType::ColorArray2D: { + const IR::U32 x{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)}, + IR::Attribute::PositionX)}; + const IR::U32 y{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)}, + IR::Attribute::PositionY)}; + const IR::U32 z{ir.CompositeExtract(coord, 2)}; + inst.SetArg(1, ir.CompositeConstruct(x, y, z)); + break; + } + case TextureType::Color1D: + case TextureType::ColorArray1D: + case TextureType::Color3D: + case TextureType::ColorCube: + case TextureType::ColorArrayCube: + case TextureType::Buffer: + // Nothing to patch here + break; + } +} + +void SubScaleImageRead(IR::Block& block, IR::Inst& inst) { + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + const auto info{inst.Flags()}; + const IR::U1 is_scaled{ir.IsImageScaled(ir.Imm32(info.descriptor_index))}; + const IR::Value coord{inst.Arg(1)}; + switch (info.type) { + case TextureType::Color2D: { + const IR::U32 x{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)}, + IR::Attribute::PositionX)}; + const IR::U32 y{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)}, + IR::Attribute::PositionY)}; + inst.SetArg(1, ir.CompositeConstruct(x, y)); + break; + } + case TextureType::ColorArray2D: { + const IR::U32 x{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)}, + IR::Attribute::PositionX)}; + const IR::U32 y{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)}, + IR::Attribute::PositionY)}; + const IR::U32 z{ir.CompositeExtract(coord, 2)}; + inst.SetArg(1, ir.CompositeConstruct(x, y, z)); + break; + } + case TextureType::Color1D: + case TextureType::ColorArray1D: + case TextureType::Color3D: + case TextureType::ColorCube: + case TextureType::ColorArrayCube: + case TextureType::Buffer: + // Nothing to patch here + break; + } +} + void PatchImageFetch(IR::Block& block, IR::Inst& inst) { IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; const auto info{inst.Flags()}; @@ -145,13 +229,23 @@ void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { break; } case IR::Opcode::ImageQueryDimensions: - PatchImageQueryDimensions(block, inst); + if (program.stage == Stage::Compute) { + PatchImageQueryDimensions(block, inst); + } break; case IR::Opcode::ImageFetch: - PatchImageFetch(block, inst); + if (is_fragment_shader) { + SubScaleImageFetch(block, inst); + } else if (program.stage == Stage::Compute) { + PatchImageFetch(block, inst); + } break; case IR::Opcode::ImageRead: - PatchImageRead(block, inst); + if (is_fragment_shader) { + SubScaleImageRead(block, inst); + } else if (program.stage == Stage::Compute) { + PatchImageRead(block, inst); + } break; default: break; -- cgit v1.2.3 From b3a9c8f108d90234c7e5e88b41f8e4bc9c163d96 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 18 Sep 2021 02:26:33 +0200 Subject: Shader: Don't rescale FragCoord if used by Shuffle --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 53 ++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index 71c9d9e6f..4d23b60c8 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -14,6 +14,52 @@ namespace Shader::Optimization { namespace { +void VisitMark(const IR::Program& program, IR::Inst& inst) { + const bool is_fragment_shader{program.stage == Stage::Fragment}; + switch (inst.GetOpcode()) { + case IR::Opcode::ShuffleIndex: + case IR::Opcode::ShuffleUp: + case IR::Opcode::ShuffleDown: + case IR::Opcode::ShuffleButterfly: { + const auto try_mark = [is_fragment_shader](IR::Inst* op) { + const IR::Attribute attr{op->Arg(0).Attribute()}; + switch (attr) { + case IR::Attribute::PositionX: + case IR::Attribute::PositionY: + if (is_fragment_shader) { + op->SetFlags(0xDEADBEEF); + } + break; + default: + break; + } + }; + const IR::Value param_1{inst.Arg(0)}; + if (param_1.IsImmediate()) { + break; + } + IR::Inst* op_a{param_1.InstRecursive()}; + if (op_a->GetOpcode() == IR::Opcode::GetAttribute) { + try_mark(op_a); + break; + } + if (op_a->GetOpcode() != IR::Opcode::BitCastF32U32) { + break; + } + const IR::Value param_2{op_a->Arg(0)}; + if (param_2.IsImmediate()) { + break; + } + IR::Inst* op_b{param_2.InstRecursive()}; + if (op_b->GetOpcode() == IR::Opcode::GetAttribute) { + try_mark(op_b); + } + break; + } + default: + break; + } +} void PatchFragCoord(IR::Block& block, IR::Inst& inst) { IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; const IR::F32 down_factor{ir.ResolutionDownFactor()}; @@ -219,7 +265,7 @@ void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { switch (attr) { case IR::Attribute::PositionX: case IR::Attribute::PositionY: - if (is_fragment_shader) { + if (is_fragment_shader && inst.Flags() != 0xDEADBEEF) { PatchFragCoord(block, inst); } break; @@ -254,6 +300,11 @@ void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { } // Anonymous namespace void RescalingPass(IR::Program& program) { + for (IR::Block* const block : program.post_order_blocks) { + for (IR::Inst& inst : block->Instructions()) { + VisitMark(program, inst); + } + } for (IR::Block* const block : program.post_order_blocks) { for (IR::Inst& inst : block->Instructions()) { Visit(program, *block, inst); -- cgit v1.2.3 From edb5844240c339846d505735d2c2e1ad731f8be7 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Fri, 17 Sep 2021 21:31:29 -0400 Subject: rescaling_pass: Fix and simplify shuffle/fragcoord pass --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 46 +++++++++++-------------- 1 file changed, 20 insertions(+), 26 deletions(-) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index 4d23b60c8..8bbaa55e4 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -14,45 +14,39 @@ namespace Shader::Optimization { namespace { -void VisitMark(const IR::Program& program, IR::Inst& inst) { +void VisitMark(const IR::Program& program, const IR::Inst& inst) { const bool is_fragment_shader{program.stage == Stage::Fragment}; + if (!is_fragment_shader) { + return; + } switch (inst.GetOpcode()) { case IR::Opcode::ShuffleIndex: case IR::Opcode::ShuffleUp: case IR::Opcode::ShuffleDown: case IR::Opcode::ShuffleButterfly: { - const auto try_mark = [is_fragment_shader](IR::Inst* op) { - const IR::Attribute attr{op->Arg(0).Attribute()}; + const IR::Value shfl_arg{inst.Arg(0)}; + if (shfl_arg.IsImmediate()) { + break; + } + const IR::Inst* const arg_inst{shfl_arg.InstRecursive()}; + if (arg_inst->GetOpcode() != IR::Opcode::BitCastU32F32) { + break; + } + const IR::Value bitcast_arg{arg_inst->Arg(0)}; + if (bitcast_arg.IsImmediate()) { + break; + } + IR::Inst* const bitcast_inst{bitcast_arg.InstRecursive()}; + if (bitcast_inst->GetOpcode() == IR::Opcode::GetAttribute) { + const IR::Attribute attr{bitcast_inst->Arg(0).Attribute()}; switch (attr) { case IR::Attribute::PositionX: case IR::Attribute::PositionY: - if (is_fragment_shader) { - op->SetFlags(0xDEADBEEF); - } + bitcast_inst->SetFlags(0xDEADBEEF); break; default: break; } - }; - const IR::Value param_1{inst.Arg(0)}; - if (param_1.IsImmediate()) { - break; - } - IR::Inst* op_a{param_1.InstRecursive()}; - if (op_a->GetOpcode() == IR::Opcode::GetAttribute) { - try_mark(op_a); - break; - } - if (op_a->GetOpcode() != IR::Opcode::BitCastF32U32) { - break; - } - const IR::Value param_2{op_a->Arg(0)}; - if (param_2.IsImmediate()) { - break; - } - IR::Inst* op_b{param_2.InstRecursive()}; - if (op_b->GetOpcode() == IR::Opcode::GetAttribute) { - try_mark(op_b); } break; } -- cgit v1.2.3 From b027fac7945184d644aa00940e528a20edcf0d06 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sat, 18 Sep 2021 00:43:41 -0400 Subject: gl_texture_cache/rescaling_pass: minor cleanup --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index 8bbaa55e4..357e41f2b 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -82,18 +82,14 @@ void PatchFragCoord(IR::Block& block, IR::Inst& inst) { [[nodiscard]] IR::U32 SubScale(IR::IREmitter& ir, const IR::U1& is_scaled, const IR::U32& value, const IR::Attribute attrib) { - if (Settings::values.resolution_info.active) { - const IR::F32 opt1{ir.Imm32(Settings::values.resolution_info.up_factor)}; - const IR::F32 base{ir.FPMul(ir.ConvertUToF(32, 32, value), opt1)}; - const IR::F32 frag_coord{ir.GetAttribute(attrib)}; - const IR::F32 opt2{ir.Imm32(Settings::values.resolution_info.down_factor)}; - const IR::F32 floor{ir.FPMul(opt1, ir.FPFloor(ir.FPMul(frag_coord, opt2)))}; - const IR::U32 deviation{ - ir.ConvertFToU(32, ir.FPAdd(base, ir.FPAdd(frag_coord, ir.FPNeg(floor))))}; - return IR::U32{ir.Select(is_scaled, deviation, value)}; - } else { - return value; - } + const IR::F32 opt1{ir.Imm32(Settings::values.resolution_info.up_factor)}; + const IR::F32 base{ir.FPMul(ir.ConvertUToF(32, 32, value), opt1)}; + const IR::F32 frag_coord{ir.GetAttribute(attrib)}; + const IR::F32 opt2{ir.Imm32(Settings::values.resolution_info.down_factor)}; + const IR::F32 floor{ir.FPMul(opt1, ir.FPFloor(ir.FPMul(frag_coord, opt2)))}; + const IR::U32 deviation{ + ir.ConvertFToU(32, ir.FPAdd(base, ir.FPAdd(frag_coord, ir.FPNeg(floor))))}; + return IR::U32{ir.Select(is_scaled, deviation, value)}; } [[nodiscard]] IR::U32 DownScale(IR::IREmitter& ir, const IR::U1& is_scaled, IR::U32 value) { -- cgit v1.2.3 From dd663844513c82a24456dbc68b9ad6665506bea9 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sun, 26 Sep 2021 22:43:06 -0400 Subject: rescaling_pass: Enable PatchImageQueryDimensions on fragment stages --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index 357e41f2b..51125f45a 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -249,6 +249,7 @@ void PatchImageRead(IR::Block& block, IR::Inst& inst) { void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { const bool is_fragment_shader{program.stage == Stage::Fragment}; + const bool is_compute_shader{program.stage == Stage::Compute}; switch (inst.GetOpcode()) { case IR::Opcode::GetAttribute: { const IR::Attribute attr{inst.Arg(0).Attribute()}; @@ -265,21 +266,19 @@ void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { break; } case IR::Opcode::ImageQueryDimensions: - if (program.stage == Stage::Compute) { - PatchImageQueryDimensions(block, inst); - } + PatchImageQueryDimensions(block, inst); break; case IR::Opcode::ImageFetch: if (is_fragment_shader) { SubScaleImageFetch(block, inst); - } else if (program.stage == Stage::Compute) { + } else if (is_compute_shader) { PatchImageFetch(block, inst); } break; case IR::Opcode::ImageRead: if (is_fragment_shader) { SubScaleImageRead(block, inst); - } else if (program.stage == Stage::Compute) { + } else if (is_compute_shader) { PatchImageRead(block, inst); } break; -- cgit v1.2.3 From 276565973f373b2dbf7f19a68a6d0304803dc2c3 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Tue, 28 Sep 2021 21:29:17 -0400 Subject: rescaling_pass: Scale ImageFetch offset if it exists Plus some code deduplication --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 96 ++++++++++--------------- 1 file changed, 37 insertions(+), 59 deletions(-) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index 51125f45a..2aa9c31dc 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -137,21 +137,22 @@ void PatchImageQueryDimensions(IR::Block& block, IR::Inst& inst) { } } -void ScaleIntegerCoord(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_scaled) { +void ScaleIntegerComposite(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_scaled, + size_t index) { + const IR::Value composite{inst.Arg(index)}; + if (composite.IsEmpty()) { + return; + } const auto info{inst.Flags()}; - const IR::Value coord{inst.Arg(1)}; + const IR::U32 x{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(composite, 0)})}; + const IR::U32 y{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(composite, 1)})}; switch (info.type) { - case TextureType::Color2D: { - const IR::U32 x{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)})}; - const IR::U32 y{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)})}; - inst.SetArg(1, ir.CompositeConstruct(x, y)); + case TextureType::Color2D: + inst.SetArg(index, ir.CompositeConstruct(x, y)); break; - } case TextureType::ColorArray2D: { - const IR::U32 x{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)})}; - const IR::U32 y{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)})}; - const IR::U32 z{ir.CompositeExtract(coord, 2)}; - inst.SetArg(1, ir.CompositeConstruct(x, y, z)); + const IR::U32 z{ir.CompositeExtract(composite, 2)}; + inst.SetArg(index, ir.CompositeConstruct(x, y, z)); break; } case TextureType::Color1D: @@ -165,27 +166,21 @@ void ScaleIntegerCoord(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_scale } } -void SubScaleImageFetch(IR::Block& block, IR::Inst& inst) { - IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; +void SubScaleCoord(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_scaled) { const auto info{inst.Flags()}; - const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))}; const IR::Value coord{inst.Arg(1)}; + const IR::U32 coord_x{ir.CompositeExtract(coord, 0)}; + const IR::U32 coord_y{ir.CompositeExtract(coord, 1)}; + + const IR::U32 scaled_x{SubScale(ir, is_scaled, coord_x, IR::Attribute::PositionX)}; + const IR::U32 scaled_y{SubScale(ir, is_scaled, coord_y, IR::Attribute::PositionY)}; switch (info.type) { - case TextureType::Color2D: { - const IR::U32 x{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)}, - IR::Attribute::PositionX)}; - const IR::U32 y{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)}, - IR::Attribute::PositionY)}; - inst.SetArg(1, ir.CompositeConstruct(x, y)); + case TextureType::Color2D: + inst.SetArg(1, ir.CompositeConstruct(scaled_x, scaled_y)); break; - } case TextureType::ColorArray2D: { - const IR::U32 x{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)}, - IR::Attribute::PositionX)}; - const IR::U32 y{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)}, - IR::Attribute::PositionY)}; const IR::U32 z{ir.CompositeExtract(coord, 2)}; - inst.SetArg(1, ir.CompositeConstruct(x, y, z)); + inst.SetArg(1, ir.CompositeConstruct(scaled_x, scaled_y, z)); break; } case TextureType::Color1D: @@ -199,57 +194,40 @@ void SubScaleImageFetch(IR::Block& block, IR::Inst& inst) { } } +void SubScaleImageFetch(IR::Block& block, IR::Inst& inst) { + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + const auto info{inst.Flags()}; + const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))}; + SubScaleCoord(ir, inst, is_scaled); + // Scale ImageFetch offset + ScaleIntegerComposite(ir, inst, is_scaled, 2); +} + void SubScaleImageRead(IR::Block& block, IR::Inst& inst) { IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; const auto info{inst.Flags()}; const IR::U1 is_scaled{ir.IsImageScaled(ir.Imm32(info.descriptor_index))}; - const IR::Value coord{inst.Arg(1)}; - switch (info.type) { - case TextureType::Color2D: { - const IR::U32 x{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)}, - IR::Attribute::PositionX)}; - const IR::U32 y{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)}, - IR::Attribute::PositionY)}; - inst.SetArg(1, ir.CompositeConstruct(x, y)); - break; - } - case TextureType::ColorArray2D: { - const IR::U32 x{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)}, - IR::Attribute::PositionX)}; - const IR::U32 y{SubScale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)}, - IR::Attribute::PositionY)}; - const IR::U32 z{ir.CompositeExtract(coord, 2)}; - inst.SetArg(1, ir.CompositeConstruct(x, y, z)); - break; - } - case TextureType::Color1D: - case TextureType::ColorArray1D: - case TextureType::Color3D: - case TextureType::ColorCube: - case TextureType::ColorArrayCube: - case TextureType::Buffer: - // Nothing to patch here - break; - } + SubScaleCoord(ir, inst, is_scaled); } void PatchImageFetch(IR::Block& block, IR::Inst& inst) { IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; const auto info{inst.Flags()}; const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))}; - ScaleIntegerCoord(ir, inst, is_scaled); + ScaleIntegerComposite(ir, inst, is_scaled, 1); + // Scale ImageFetch offset + ScaleIntegerComposite(ir, inst, is_scaled, 2); } void PatchImageRead(IR::Block& block, IR::Inst& inst) { IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; const auto info{inst.Flags()}; const IR::U1 is_scaled{ir.IsImageScaled(ir.Imm32(info.descriptor_index))}; - ScaleIntegerCoord(ir, inst, is_scaled); + ScaleIntegerComposite(ir, inst, is_scaled, 1); } void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { const bool is_fragment_shader{program.stage == Stage::Fragment}; - const bool is_compute_shader{program.stage == Stage::Compute}; switch (inst.GetOpcode()) { case IR::Opcode::GetAttribute: { const IR::Attribute attr{inst.Arg(0).Attribute()}; @@ -271,14 +249,14 @@ void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { case IR::Opcode::ImageFetch: if (is_fragment_shader) { SubScaleImageFetch(block, inst); - } else if (is_compute_shader) { + } else { PatchImageFetch(block, inst); } break; case IR::Opcode::ImageRead: if (is_fragment_shader) { SubScaleImageRead(block, inst); - } else if (is_compute_shader) { + } else { PatchImageRead(block, inst); } break; -- cgit v1.2.3 From 99eec162da567ce08a7ab6ce4d1f4b5fa8b5af5e Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Tue, 28 Sep 2021 21:37:54 -0400 Subject: rescaling_pass: Logic simplification and minor style cleanup --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 49 +++++++++---------------- 1 file changed, 17 insertions(+), 32 deletions(-) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index 2aa9c31dc..0d642dd0d 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -14,11 +14,7 @@ namespace Shader::Optimization { namespace { -void VisitMark(const IR::Program& program, const IR::Inst& inst) { - const bool is_fragment_shader{program.stage == Stage::Fragment}; - if (!is_fragment_shader) { - return; - } +void VisitMark(const IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::ShuffleIndex: case IR::Opcode::ShuffleUp: @@ -54,6 +50,7 @@ void VisitMark(const IR::Program& program, const IR::Inst& inst) { break; } } + void PatchFragCoord(IR::Block& block, IR::Inst& inst) { IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; const IR::F32 down_factor{ir.ResolutionDownFactor()}; @@ -64,50 +61,35 @@ void PatchFragCoord(IR::Block& block, IR::Inst& inst) { [[nodiscard]] IR::U32 Scale(IR::IREmitter& ir, const IR::U1& is_scaled, const IR::U32& value) { IR::U32 scaled_value{value}; - bool changed{}; if (const u32 up_scale = Settings::values.resolution_info.up_scale; up_scale != 1) { scaled_value = ir.IMul(scaled_value, ir.Imm32(up_scale)); - changed = true; } if (const u32 down_shift = Settings::values.resolution_info.down_shift; down_shift != 0) { scaled_value = ir.ShiftRightArithmetic(scaled_value, ir.Imm32(down_shift)); - changed = true; - } - if (changed) { - return IR::U32{ir.Select(is_scaled, scaled_value, value)}; - } else { - return value; } + return IR::U32{ir.Select(is_scaled, scaled_value, value)}; } [[nodiscard]] IR::U32 SubScale(IR::IREmitter& ir, const IR::U1& is_scaled, const IR::U32& value, const IR::Attribute attrib) { - const IR::F32 opt1{ir.Imm32(Settings::values.resolution_info.up_factor)}; - const IR::F32 base{ir.FPMul(ir.ConvertUToF(32, 32, value), opt1)}; + const IR::F32 up_factor{ir.Imm32(Settings::values.resolution_info.up_factor)}; + const IR::F32 base{ir.FPMul(ir.ConvertUToF(32, 32, value), up_factor)}; const IR::F32 frag_coord{ir.GetAttribute(attrib)}; - const IR::F32 opt2{ir.Imm32(Settings::values.resolution_info.down_factor)}; - const IR::F32 floor{ir.FPMul(opt1, ir.FPFloor(ir.FPMul(frag_coord, opt2)))}; - const IR::U32 deviation{ - ir.ConvertFToU(32, ir.FPAdd(base, ir.FPAdd(frag_coord, ir.FPNeg(floor))))}; - return IR::U32{ir.Select(is_scaled, deviation, value)}; + const IR::F32 down_factor{ir.Imm32(Settings::values.resolution_info.down_factor)}; + const IR::F32 floor{ir.FPMul(up_factor, ir.FPFloor(ir.FPMul(frag_coord, down_factor)))}; + const IR::F16F32F64 deviation{ir.FPAdd(base, ir.FPAdd(frag_coord, ir.FPNeg(floor)))}; + return IR::U32{ir.Select(is_scaled, ir.ConvertFToU(32, deviation), value)}; } -[[nodiscard]] IR::U32 DownScale(IR::IREmitter& ir, const IR::U1& is_scaled, IR::U32 value) { +[[nodiscard]] IR::U32 DownScale(IR::IREmitter& ir, const IR::U1& is_scaled, const IR::U32& value) { IR::U32 scaled_value{value}; - bool changed{}; if (const u32 down_shift = Settings::values.resolution_info.down_shift; down_shift != 0) { scaled_value = ir.ShiftLeftLogical(scaled_value, ir.Imm32(down_shift)); - changed = true; } if (const u32 up_scale = Settings::values.resolution_info.up_scale; up_scale != 1) { scaled_value = ir.IDiv(scaled_value, ir.Imm32(up_scale)); - changed = true; - } - if (changed) { - return IR::U32{ir.Select(is_scaled, scaled_value, value)}; - } else { - return value; } + return IR::U32{ir.Select(is_scaled, scaled_value, value)}; } void PatchImageQueryDimensions(IR::Block& block, IR::Inst& inst) { @@ -267,9 +249,12 @@ void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { } // Anonymous namespace void RescalingPass(IR::Program& program) { - for (IR::Block* const block : program.post_order_blocks) { - for (IR::Inst& inst : block->Instructions()) { - VisitMark(program, inst); + const bool is_fragment_shader{program.stage == Stage::Fragment}; + if (is_fragment_shader) { + for (IR::Block* const block : program.post_order_blocks) { + for (IR::Inst& inst : block->Instructions()) { + VisitMark(inst); + } } } for (IR::Block* const block : program.post_order_blocks) { -- cgit v1.2.3 From 581ea900627b398c2fa06b70facd5dcd8bbb7d68 Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Wed, 29 Sep 2021 20:53:30 -0400 Subject: rescaling_pass: Fix IR errors when unscalable texture types are encountered --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index 0d642dd0d..a5fa4ee83 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -14,6 +14,22 @@ namespace Shader::Optimization { namespace { +[[nodiscard]] bool IsTextureTypeRescalable(TextureType type) { + switch (type) { + case TextureType::Color2D: + case TextureType::ColorArray2D: + return true; + case TextureType::Color1D: + case TextureType::ColorArray1D: + case TextureType::Color3D: + case TextureType::ColorCube: + case TextureType::ColorArrayCube: + case TextureType::Buffer: + break; + } + return false; +} + void VisitMark(const IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::ShuffleIndex: @@ -179,6 +195,9 @@ void SubScaleCoord(IR::IREmitter& ir, IR::Inst& inst, const IR::U1& is_scaled) { void SubScaleImageFetch(IR::Block& block, IR::Inst& inst) { IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; const auto info{inst.Flags()}; + if (!IsTextureTypeRescalable(info.type)) { + return; + } const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))}; SubScaleCoord(ir, inst, is_scaled); // Scale ImageFetch offset @@ -188,6 +207,9 @@ void SubScaleImageFetch(IR::Block& block, IR::Inst& inst) { void SubScaleImageRead(IR::Block& block, IR::Inst& inst) { IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; const auto info{inst.Flags()}; + if (!IsTextureTypeRescalable(info.type)) { + return; + } const IR::U1 is_scaled{ir.IsImageScaled(ir.Imm32(info.descriptor_index))}; SubScaleCoord(ir, inst, is_scaled); } @@ -195,6 +217,9 @@ void SubScaleImageRead(IR::Block& block, IR::Inst& inst) { void PatchImageFetch(IR::Block& block, IR::Inst& inst) { IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; const auto info{inst.Flags()}; + if (!IsTextureTypeRescalable(info.type)) { + return; + } const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))}; ScaleIntegerComposite(ir, inst, is_scaled, 1); // Scale ImageFetch offset @@ -204,6 +229,9 @@ void PatchImageFetch(IR::Block& block, IR::Inst& inst) { void PatchImageRead(IR::Block& block, IR::Inst& inst) { IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; const auto info{inst.Flags()}; + if (!IsTextureTypeRescalable(info.type)) { + return; + } const IR::U1 is_scaled{ir.IsImageScaled(ir.Imm32(info.descriptor_index))}; ScaleIntegerComposite(ir, inst, is_scaled, 1); } -- cgit v1.2.3 From de1c8c5c2c3131bb122351e676014cdc7c442e78 Mon Sep 17 00:00:00 2001 From: FernandoS27 Date: Fri, 29 Oct 2021 17:02:57 +0200 Subject: Texture Cahe/Shader decompiler: Resize PointSize on rescaling, refactor and make reaper more agressive on 4Gb GPUs. --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index a5fa4ee83..81098c038 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -75,6 +75,14 @@ void PatchFragCoord(IR::Block& block, IR::Inst& inst) { inst.ReplaceUsesWith(downscaled_frag_coord); } +void PatchPointSize(IR::Block& block, IR::Inst& inst) { + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + const IR::F32 point_value{inst.Arg(1)}; + const IR::F32 up_factor{ir.FPRecip(ir.ResolutionDownFactor())}; + const IR::F32 upscaled_point_value{ir.FPMul(point_value, up_factor)}; + inst.SetArg(1, upscaled_point_value); +} + [[nodiscard]] IR::U32 Scale(IR::IREmitter& ir, const IR::U1& is_scaled, const IR::U32& value) { IR::U32 scaled_value{value}; if (const u32 up_scale = Settings::values.resolution_info.up_scale; up_scale != 1) { @@ -253,6 +261,19 @@ void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { } break; } + case IR::Opcode::SetAttribute: { + const IR::Attribute attr{inst.Arg(0).Attribute()}; + switch (attr) { + case IR::Attribute::PointSize: + if (inst.Flags() != 0xDEADBEEF) { + PatchPointSize(block, inst); + } + break; + default: + break; + } + break; + } case IR::Opcode::ImageQueryDimensions: PatchImageQueryDimensions(block, inst); break; -- cgit v1.2.3 From 6f9869096378a5100620b3f2b685d61bf8ccae16 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 30 Oct 2021 01:47:18 +0200 Subject: ShaderCache: Better fix for Shuffling gl_FragCoord --- src/shader_recompiler/ir_opt/rescaling_pass.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src/shader_recompiler/ir_opt/rescaling_pass.cpp') diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index 81098c038..c28500dd1 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp @@ -30,7 +30,7 @@ namespace { return false; } -void VisitMark(const IR::Inst& inst) { +void VisitMark(IR::Block& block, IR::Inst& inst) { switch (inst.GetOpcode()) { case IR::Opcode::ShuffleIndex: case IR::Opcode::ShuffleUp: @@ -49,19 +49,30 @@ void VisitMark(const IR::Inst& inst) { break; } IR::Inst* const bitcast_inst{bitcast_arg.InstRecursive()}; + bool must_patch_outside = false; if (bitcast_inst->GetOpcode() == IR::Opcode::GetAttribute) { const IR::Attribute attr{bitcast_inst->Arg(0).Attribute()}; switch (attr) { case IR::Attribute::PositionX: case IR::Attribute::PositionY: bitcast_inst->SetFlags(0xDEADBEEF); + must_patch_outside = true; break; default: break; } } + if (must_patch_outside) { + const auto it{IR::Block::InstructionList::s_iterator_to(inst)}; + IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; + const IR::F32 new_inst{&*block.PrependNewInst(it, inst)}; + const IR::F32 up_factor{ir.FPRecip(ir.ResolutionDownFactor())}; + const IR::Value converted{ir.FPMul(new_inst, up_factor)}; + inst.ReplaceUsesWith(converted); + } break; } + default: break; } @@ -302,7 +313,7 @@ void RescalingPass(IR::Program& program) { if (is_fragment_shader) { for (IR::Block* const block : program.post_order_blocks) { for (IR::Inst& inst : block->Instructions()) { - VisitMark(inst); + VisitMark(*block, inst); } } } -- cgit v1.2.3