diff options
| author | 2021-04-23 08:17:53 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:29 -0400 | |
| commit | 50eb03382e8ac8eb4aeb7cdc488a7ee097fec39d (patch) | |
| tree | ff92fe55869e683ce0978621983b723d7095235e /src/shader_recompiler/ir_opt/constant_propagation_pass.cpp | |
| parent | vulkan_device: Require shaderClipDistance and shaderCullDistance features (diff) | |
| download | yuzu-50eb03382e8ac8eb4aeb7cdc488a7ee097fec39d.tar.gz yuzu-50eb03382e8ac8eb4aeb7cdc488a7ee097fec39d.tar.xz yuzu-50eb03382e8ac8eb4aeb7cdc488a7ee097fec39d.zip | |
shader: Fix error checking in bitfieldExtract and implement bitfieldInsert folding
Diffstat (limited to 'src/shader_recompiler/ir_opt/constant_propagation_pass.cpp')
| -rw-r--r-- | src/shader_recompiler/ir_opt/constant_propagation_pass.cpp | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp index 770d3de61..f16c5e8f6 100644 --- a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp +++ b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp | |||
| @@ -553,7 +553,7 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) { | |||
| 553 | return; | 553 | return; |
| 554 | case IR::Opcode::BitFieldUExtract: | 554 | case IR::Opcode::BitFieldUExtract: |
| 555 | FoldWhenAllImmediates(inst, [](u32 base, u32 shift, u32 count) { | 555 | FoldWhenAllImmediates(inst, [](u32 base, u32 shift, u32 count) { |
| 556 | if (static_cast<size_t>(shift) + static_cast<size_t>(count) > Common::BitSize<u32>()) { | 556 | if (static_cast<size_t>(shift) + static_cast<size_t>(count) > 32) { |
| 557 | throw LogicError("Undefined result in {}({}, {}, {})", IR::Opcode::BitFieldUExtract, | 557 | throw LogicError("Undefined result in {}({}, {}, {})", IR::Opcode::BitFieldUExtract, |
| 558 | base, shift, count); | 558 | base, shift, count); |
| 559 | } | 559 | } |
| @@ -563,13 +563,22 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) { | |||
| 563 | case IR::Opcode::BitFieldSExtract: | 563 | case IR::Opcode::BitFieldSExtract: |
| 564 | FoldWhenAllImmediates(inst, [](s32 base, u32 shift, u32 count) { | 564 | FoldWhenAllImmediates(inst, [](s32 base, u32 shift, u32 count) { |
| 565 | const size_t back_shift{static_cast<size_t>(shift) + static_cast<size_t>(count)}; | 565 | const size_t back_shift{static_cast<size_t>(shift) + static_cast<size_t>(count)}; |
| 566 | if (back_shift > Common::BitSize<s32>()) { | 566 | const size_t left_shift{32 - back_shift}; |
| 567 | const size_t right_shift{static_cast<size_t>(32 - count)}; | ||
| 568 | if (back_shift >= 32 || left_shift >= 32 || right_shift >= 32) { | ||
| 567 | throw LogicError("Undefined result in {}({}, {}, {})", IR::Opcode::BitFieldSExtract, | 569 | throw LogicError("Undefined result in {}({}, {}, {})", IR::Opcode::BitFieldSExtract, |
| 568 | base, shift, count); | 570 | base, shift, count); |
| 569 | } | 571 | } |
| 570 | const size_t left_shift{Common::BitSize<s32>() - back_shift}; | 572 | return static_cast<u32>((base << left_shift) >> right_shift); |
| 571 | return static_cast<u32>(static_cast<s32>(base << left_shift) >> | 573 | }); |
| 572 | static_cast<size_t>(Common::BitSize<s32>() - count)); | 574 | return; |
| 575 | case IR::Opcode::BitFieldInsert: | ||
| 576 | FoldWhenAllImmediates(inst, [](u32 base, u32 insert, u32 offset, u32 bits) { | ||
| 577 | if (bits >= 32 || offset >= 32) { | ||
| 578 | throw LogicError("Undefined result in {}({}, {}, {}, {})", | ||
| 579 | IR::Opcode::BitFieldInsert, base, insert, offset, bits); | ||
| 580 | } | ||
| 581 | return (base & ~(~(~0u << bits) << offset)) | (insert << offset); | ||
| 573 | }); | 582 | }); |
| 574 | return; | 583 | return; |
| 575 | case IR::Opcode::BranchConditional: | 584 | case IR::Opcode::BranchConditional: |