mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-26 21:36:27 -05:00
ShaderDecompiler: Add initial support for rescaling.
This commit is contained in:
parent
37ef9c9130
commit
360e897ccd
2 changed files with 73 additions and 0 deletions
72
src/shader_recompiler/ir_opt/rescaling_pass.cpp
Normal file
72
src/shader_recompiler/ir_opt/rescaling_pass.cpp
Normal file
|
@ -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
|
|
@ -172,6 +172,7 @@ struct Info {
|
||||||
bool uses_global_memory{};
|
bool uses_global_memory{};
|
||||||
bool uses_atomic_image_u32{};
|
bool uses_atomic_image_u32{};
|
||||||
bool uses_shadow_lod{};
|
bool uses_shadow_lod{};
|
||||||
|
bool requires_rescaling_uniform{};
|
||||||
|
|
||||||
IR::Type used_constant_buffer_types{};
|
IR::Type used_constant_buffer_types{};
|
||||||
IR::Type used_storage_buffer_types{};
|
IR::Type used_storage_buffer_types{};
|
||||||
|
|
Loading…
Reference in a new issue