| 108 | } |
| 109 | |
| 110 | spv_result_t ValidateDecorationTarget(ValidationState_t& _, spv::Decoration dec, |
| 111 | const Instruction* inst, |
| 112 | const Instruction* target) { |
| 113 | auto fail = [&_, dec, inst, target](uint32_t vuid) -> DiagnosticStream { |
| 114 | DiagnosticStream ds = std::move( |
| 115 | _.diag(SPV_ERROR_INVALID_ID, inst) |
| 116 | << _.VkErrorID(vuid) << _.SpvDecorationString(dec) |
| 117 | << " decoration on target <id> " << _.getIdName(target->id()) << " "); |
| 118 | return ds; |
| 119 | }; |
| 120 | switch (dec) { |
| 121 | case spv::Decoration::SpecId: |
| 122 | if (target->opcode() != spv::Op::OpSpecConstantTrue && |
| 123 | target->opcode() != spv::Op::OpSpecConstantFalse && |
| 124 | target->opcode() != spv::Op::OpSpecConstant && |
| 125 | target->opcode() != spv::Op::OpSpecConstantDataKHR) { |
| 126 | return fail(0) << "must be OpSpecConstantTrue, OpSpecConstantFalse, " |
| 127 | "OpSpecConstant, or OpSpecConstantDataKHR"; |
| 128 | } |
| 129 | break; |
| 130 | case spv::Decoration::Block: |
| 131 | case spv::Decoration::BufferBlock: |
| 132 | case spv::Decoration::GLSLShared: |
| 133 | case spv::Decoration::GLSLPacked: |
| 134 | case spv::Decoration::CPacked: |
| 135 | if (target->opcode() != spv::Op::OpTypeStruct) { |
| 136 | return fail(0) << "must be a structure type"; |
| 137 | } |
| 138 | break; |
| 139 | case spv::Decoration::ArrayStride: |
| 140 | if (target->opcode() != spv::Op::OpTypeArray && |
| 141 | target->opcode() != spv::Op::OpTypeRuntimeArray && |
| 142 | target->opcode() != spv::Op::OpTypePointer && |
| 143 | target->opcode() != spv::Op::OpTypeUntypedPointerKHR) { |
| 144 | return fail(0) << "must be an array or pointer type"; |
| 145 | } |
| 146 | break; |
| 147 | case spv::Decoration::BuiltIn: |
| 148 | if (target->opcode() != spv::Op::OpVariable && |
| 149 | target->opcode() != spv::Op::OpUntypedVariableKHR && |
| 150 | !spvOpcodeIsConstant(target->opcode())) { |
| 151 | return _.diag(SPV_ERROR_INVALID_DATA, inst) |
| 152 | << "BuiltIns can only target variables, structure members or " |
| 153 | "constants"; |
| 154 | } |
| 155 | if (_.HasCapability(spv::Capability::Shader) && |
| 156 | inst->GetOperandAs<spv::BuiltIn>(2) == spv::BuiltIn::WorkgroupSize) { |
| 157 | if (!spvOpcodeIsConstant(target->opcode())) { |
| 158 | return fail(0) << "must be a constant for WorkgroupSize"; |
| 159 | } |
| 160 | } else if (target->opcode() != spv::Op::OpVariable && |
| 161 | target->opcode() != spv::Op::OpUntypedVariableKHR) { |
| 162 | return fail(0) << "must be a variable"; |
| 163 | } |
| 164 | break; |
| 165 | case spv::Decoration::NoPerspective: |
| 166 | case spv::Decoration::Flat: |
| 167 | case spv::Decoration::Patch: |
no test coverage detected