Prechádzať zdrojové kódy

ShaderCache: Better fix for Shuffling gl_FragCoord

Fernando Sahmkow 4 rokov pred
rodič
commit
6f98690963

+ 13 - 2
src/shader_recompiler/ir_opt/rescaling_pass.cpp

@@ -30,7 +30,7 @@ namespace {
     return false;
     return false;
 }
 }
 
 
-void VisitMark(const IR::Inst& inst) {
+void VisitMark(IR::Block& block, IR::Inst& inst) {
     switch (inst.GetOpcode()) {
     switch (inst.GetOpcode()) {
     case IR::Opcode::ShuffleIndex:
     case IR::Opcode::ShuffleIndex:
     case IR::Opcode::ShuffleUp:
     case IR::Opcode::ShuffleUp:
@@ -49,19 +49,30 @@ void VisitMark(const IR::Inst& inst) {
             break;
             break;
         }
         }
         IR::Inst* const bitcast_inst{bitcast_arg.InstRecursive()};
         IR::Inst* const bitcast_inst{bitcast_arg.InstRecursive()};
+        bool must_patch_outside = false;
         if (bitcast_inst->GetOpcode() == IR::Opcode::GetAttribute) {
         if (bitcast_inst->GetOpcode() == IR::Opcode::GetAttribute) {
             const IR::Attribute attr{bitcast_inst->Arg(0).Attribute()};
             const IR::Attribute attr{bitcast_inst->Arg(0).Attribute()};
             switch (attr) {
             switch (attr) {
             case IR::Attribute::PositionX:
             case IR::Attribute::PositionX:
             case IR::Attribute::PositionY:
             case IR::Attribute::PositionY:
                 bitcast_inst->SetFlags<u32>(0xDEADBEEF);
                 bitcast_inst->SetFlags<u32>(0xDEADBEEF);
+                must_patch_outside = true;
                 break;
                 break;
             default:
             default:
                 break;
                 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;
         break;
     }
     }
+
     default:
     default:
         break;
         break;
     }
     }
@@ -302,7 +313,7 @@ void RescalingPass(IR::Program& program) {
     if (is_fragment_shader) {
     if (is_fragment_shader) {
         for (IR::Block* const block : program.post_order_blocks) {
         for (IR::Block* const block : program.post_order_blocks) {
             for (IR::Inst& inst : block->Instructions()) {
             for (IR::Inst& inst : block->Instructions()) {
-                VisitMark(inst);
+                VisitMark(*block, inst);
             }
             }
         }
         }
     }
     }