| 71 | } |
| 72 | |
| 73 | void UpgradeMemoryModel::UpgradeInstructions() { |
| 74 | // Coherent and Volatile decorations are deprecated. Remove them and replace |
| 75 | // with flags on the memory/image operations. The decorations can occur on |
| 76 | // OpVariable, OpFunctionParameter (of pointer type) and OpStructType (member |
| 77 | // decoration). Trace from the decoration target(s) to the final memory/image |
| 78 | // instructions. Additionally, Workgroup storage class variables and function |
| 79 | // parameters are implicitly coherent in GLSL450. |
| 80 | |
| 81 | // Upgrade modf and frexp first since they generate new stores. |
| 82 | // In SPIR-V 1.4 or later, normalize OpCopyMemory* access operands. |
| 83 | for (auto& func : *get_module()) { |
| 84 | func.ForEachInst([this](Instruction* inst) { |
| 85 | if (inst->opcode() == spv::Op::OpExtInst) { |
| 86 | auto ext_inst = inst->GetSingleWordInOperand(1u); |
| 87 | if (ext_inst == GLSLstd450Modf || ext_inst == GLSLstd450Frexp) { |
| 88 | auto import = |
| 89 | get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0u)); |
| 90 | if (import->GetInOperand(0u).AsString() == "GLSL.std.450") { |
| 91 | UpgradeExtInst(inst); |
| 92 | } |
| 93 | } |
| 94 | } else if (get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 4)) { |
| 95 | if (inst->opcode() == spv::Op::OpCopyMemory || |
| 96 | inst->opcode() == spv::Op::OpCopyMemorySized) { |
| 97 | uint32_t start_operand = |
| 98 | inst->opcode() == spv::Op::OpCopyMemory ? 2u : 3u; |
| 99 | if (inst->NumInOperands() > start_operand) { |
| 100 | auto num_access_words = MemoryAccessNumWords( |
| 101 | inst->GetSingleWordInOperand(start_operand)); |
| 102 | if ((num_access_words + start_operand) == inst->NumInOperands()) { |
| 103 | // There is a single memory access operand. Duplicate it to have a |
| 104 | // separate operand for both source and target. |
| 105 | for (uint32_t i = 0; i < num_access_words; ++i) { |
| 106 | auto operand = inst->GetInOperand(start_operand + i); |
| 107 | inst->AddOperand(std::move(operand)); |
| 108 | } |
| 109 | } |
| 110 | } else { |
| 111 | // Add two memory access operands. |
| 112 | inst->AddOperand({SPV_OPERAND_TYPE_MEMORY_ACCESS, |
| 113 | {uint32_t(spv::MemoryAccessMask::MaskNone)}}); |
| 114 | inst->AddOperand({SPV_OPERAND_TYPE_MEMORY_ACCESS, |
| 115 | {uint32_t(spv::MemoryAccessMask::MaskNone)}}); |
| 116 | } |
| 117 | } |
| 118 | } |
| 119 | }); |
| 120 | } |
| 121 | |
| 122 | UpgradeMemoryAndImages(); |
| 123 | UpgradeAtomics(); |
| 124 | } |
| 125 | |
| 126 | void UpgradeMemoryModel::UpgradeMemoryAndImages() { |
| 127 | for (auto& func : *get_module()) { |
nothing calls this directly
no test coverage detected