Skip to content

Commit 3ab0d22

Browse files
alan-bakerdneto0
andauthored
Support SPV_KHR_untyped_pointers (KhronosGroup#5736)
* Support SPV_KHR_untyped_pointers Covers: - assembler - disassembler - validator fix copyright Validate OpTypeUntypedPointerKHR * Disallow an untyped pointer in a typed pointer * Validate capability requirements for untyped pointer * Allow duplicate untyped pointer declarations Add round trip tests Validate OpUntypedVariableKHR Validate untyped access chains * Add a test for opcodes that generate untyped pointers * simplify some checks for operands needing types * validate OpUnypedAccessChainKHR, OpUntypedInBoundsAccessChainKHR, OpUntypedPtrAccessChainKHR, OpUntypedInBoundsPtrAccessChainKHR Unify variable validation Validate OpCopyMemorySized * Fix some opcode tests to accound for untyped pointers * Add validation for OpCopyMemorySized for shaders and untyped pointers * fix up tests Validate pointer comparisons and bitcast * Update more helpers * Fix entry validation to allow OpUntypedVariableKHR * Validate OpPtrEqual, OpPtrNotEqual and OpPtrDiff * Validate OpBitcast Validate atomics and untyped pointers Make interface variable validation aware of untyped pointers * Check OpUntypedVariableKHR in interface validation More untyped pointer validation * Validate interfaces more thoroughly * Validate layouts for untyped pointer uses * Improve capability checks for vulkan with OpTypeUntypedPointerKHR * workgroup member explicit layout validation updates More validation * validate function arguments and parameters * handle untyped pointer and variable in more places Add a friendly assembly name for untyped pointers Update OpCopyMemory validation and tests Fix test for token update Fixes for validation * Allow typed pointers to contain untyped pointers * Fix decoration validation * add untyped pointer as a case for size and alignments Fix interface validation * Grabbed the wrong storage class operand for untyped variables * Add ability to specify assembler options in validation tests Add passthrough validation for OpUntypedArrayLengthKHR More validation of untyped pointers * Validate OpUntypedArrayLengthKHR * Validate layout for OpLoad, OpStore, and OpUntypedArrayLengthKHR Validation support for cooperative matrix and untyped pointers * Allow untyped pointers for cooperative matrix KHR load and store Updates to match spec * Remove extra capability references * Swap untyped variable data type and storage class operands * update validation of variables * update deps --------- Co-authored-by: David Neto <[email protected]>
1 parent 6248fda commit 3ab0d22

34 files changed

+3657
-329
lines changed

DEPS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ vars = {
1414

1515
're2_revision': '6dcd83d60f7944926bfd308cc13979fc53dd69ca',
1616

17-
'spirv_headers_revision': '41a8eb27f1a7554dadfcdd45819954eaa94935e6',
17+
'spirv_headers_revision': 'db5a00f8cebe81146cafabf89019674a3c4bf03d',
1818
}
1919

2020
deps = {

source/name_mapper.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,11 @@ spv_result_t FriendlyNameMapper::ParseInstruction(
256256
inst.words[2]) +
257257
"_" + NameForId(inst.words[3]));
258258
break;
259+
case spv::Op::OpTypeUntypedPointerKHR:
260+
SaveName(result_id, std::string("_ptr_") +
261+
NameForEnumOperand(SPV_OPERAND_TYPE_STORAGE_CLASS,
262+
inst.words[2]));
263+
break;
259264
case spv::Op::OpTypePipe:
260265
SaveName(result_id,
261266
std::string("Pipe") +

source/opcode.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,15 +287,19 @@ int32_t spvOpcodeIsComposite(const spv::Op opcode) {
287287
bool spvOpcodeReturnsLogicalVariablePointer(const spv::Op opcode) {
288288
switch (opcode) {
289289
case spv::Op::OpVariable:
290+
case spv::Op::OpUntypedVariableKHR:
290291
case spv::Op::OpAccessChain:
291292
case spv::Op::OpInBoundsAccessChain:
293+
case spv::Op::OpUntypedAccessChainKHR:
294+
case spv::Op::OpUntypedInBoundsAccessChainKHR:
292295
case spv::Op::OpFunctionParameter:
293296
case spv::Op::OpImageTexelPointer:
294297
case spv::Op::OpCopyObject:
295298
case spv::Op::OpSelect:
296299
case spv::Op::OpPhi:
297300
case spv::Op::OpFunctionCall:
298301
case spv::Op::OpPtrAccessChain:
302+
case spv::Op::OpUntypedPtrAccessChainKHR:
299303
case spv::Op::OpLoad:
300304
case spv::Op::OpConstantNull:
301305
case spv::Op::OpRawAccessChainNV:
@@ -308,8 +312,11 @@ bool spvOpcodeReturnsLogicalVariablePointer(const spv::Op opcode) {
308312
int32_t spvOpcodeReturnsLogicalPointer(const spv::Op opcode) {
309313
switch (opcode) {
310314
case spv::Op::OpVariable:
315+
case spv::Op::OpUntypedVariableKHR:
311316
case spv::Op::OpAccessChain:
312317
case spv::Op::OpInBoundsAccessChain:
318+
case spv::Op::OpUntypedAccessChainKHR:
319+
case spv::Op::OpUntypedInBoundsAccessChainKHR:
313320
case spv::Op::OpFunctionParameter:
314321
case spv::Op::OpImageTexelPointer:
315322
case spv::Op::OpCopyObject:
@@ -351,6 +358,7 @@ int32_t spvOpcodeGeneratesType(spv::Op op) {
351358
// spv::Op::OpTypeAccelerationStructureNV
352359
case spv::Op::OpTypeRayQueryKHR:
353360
case spv::Op::OpTypeHitObjectNV:
361+
case spv::Op::OpTypeUntypedPointerKHR:
354362
return true;
355363
default:
356364
// In particular, OpTypeForwardPointer does not generate a type,
@@ -792,3 +800,16 @@ bool spvOpcodeIsBit(spv::Op opcode) {
792800
return false;
793801
}
794802
}
803+
804+
bool spvOpcodeGeneratesUntypedPointer(spv::Op opcode) {
805+
switch (opcode) {
806+
case spv::Op::OpUntypedVariableKHR:
807+
case spv::Op::OpUntypedAccessChainKHR:
808+
case spv::Op::OpUntypedInBoundsAccessChainKHR:
809+
case spv::Op::OpUntypedPtrAccessChainKHR:
810+
case spv::Op::OpUntypedInBoundsPtrAccessChainKHR:
811+
return true;
812+
default:
813+
return false;
814+
}
815+
}

source/opcode.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,7 @@ bool spvOpcodeIsBit(spv::Op opcode);
162162
// Gets the name of an instruction, without the "Op" prefix.
163163
const char* spvOpcodeString(const spv::Op opcode);
164164

165+
// Returns true for opcodes that generate an untyped pointer result.
166+
bool spvOpcodeGeneratesUntypedPointer(spv::Op opcode);
167+
165168
#endif // SOURCE_OPCODE_H_

source/val/validate_adjacency.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,15 @@ spv_result_t ValidateAdjacency(ValidationState_t& _) {
117117
"first instructions in the first block.";
118118
}
119119
break;
120+
case spv::Op::OpUntypedVariableKHR:
121+
if (inst.GetOperandAs<spv::StorageClass>(2) ==
122+
spv::StorageClass::Function &&
123+
adjacency_status != IN_ENTRY_BLOCK) {
124+
return _.diag(SPV_ERROR_INVALID_DATA, &inst)
125+
<< "All OpUntypedVariableKHR instructions in a function must "
126+
"be the first instructions in the first block.";
127+
}
128+
break;
120129
default:
121130
adjacency_status = PHI_AND_VAR_INVALID;
122131
break;

source/val/validate_annotation.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, spv::Decoration dec,
129129
break;
130130
case spv::Decoration::BuiltIn:
131131
if (target->opcode() != spv::Op::OpVariable &&
132+
target->opcode() != spv::Op::OpUntypedVariableKHR &&
132133
!spvOpcodeIsConstant(target->opcode())) {
133134
return _.diag(SPV_ERROR_INVALID_DATA, inst)
134135
<< "BuiltIns can only target variables, structure members or "
@@ -139,7 +140,8 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, spv::Decoration dec,
139140
if (!spvOpcodeIsConstant(target->opcode())) {
140141
return fail(0) << "must be a constant for WorkgroupSize";
141142
}
142-
} else if (target->opcode() != spv::Op::OpVariable) {
143+
} else if (target->opcode() != spv::Op::OpVariable &&
144+
target->opcode() != spv::Op::OpUntypedVariableKHR) {
143145
return fail(0) << "must be a variable";
144146
}
145147
break;
@@ -161,11 +163,12 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, spv::Decoration dec,
161163
case spv::Decoration::RestrictPointer:
162164
case spv::Decoration::AliasedPointer:
163165
if (target->opcode() != spv::Op::OpVariable &&
166+
target->opcode() != spv::Op::OpUntypedVariableKHR &&
164167
target->opcode() != spv::Op::OpFunctionParameter &&
165168
target->opcode() != spv::Op::OpRawAccessChainNV) {
166169
return fail(0) << "must be a memory object declaration";
167170
}
168-
if (_.GetIdOpcode(target->type_id()) != spv::Op::OpTypePointer) {
171+
if (!_.IsPointerType(target->type_id())) {
169172
return fail(0) << "must be a pointer type";
170173
}
171174
break;
@@ -176,7 +179,8 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, spv::Decoration dec,
176179
case spv::Decoration::Binding:
177180
case spv::Decoration::DescriptorSet:
178181
case spv::Decoration::InputAttachmentIndex:
179-
if (target->opcode() != spv::Op::OpVariable) {
182+
if (target->opcode() != spv::Op::OpVariable &&
183+
target->opcode() != spv::Op::OpUntypedVariableKHR) {
180184
return fail(0) << "must be a variable";
181185
}
182186
break;

source/val/validate_atomics.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,44 @@ spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
183183
if (!_.GetPointerTypeInfo(pointer_type, &data_type, &storage_class)) {
184184
return _.diag(SPV_ERROR_INVALID_DATA, inst)
185185
<< spvOpcodeString(opcode)
186-
<< ": expected Pointer to be of type OpTypePointer";
186+
<< ": expected Pointer to be a pointer type";
187+
}
188+
189+
// If the pointer is an untyped pointer, get the data type elsewhere.
190+
if (data_type == 0) {
191+
switch (opcode) {
192+
case spv::Op::OpAtomicLoad:
193+
case spv::Op::OpAtomicExchange:
194+
case spv::Op::OpAtomicFAddEXT:
195+
case spv::Op::OpAtomicCompareExchange:
196+
case spv::Op::OpAtomicCompareExchangeWeak:
197+
case spv::Op::OpAtomicIIncrement:
198+
case spv::Op::OpAtomicIDecrement:
199+
case spv::Op::OpAtomicIAdd:
200+
case spv::Op::OpAtomicISub:
201+
case spv::Op::OpAtomicSMin:
202+
case spv::Op::OpAtomicUMin:
203+
case spv::Op::OpAtomicFMinEXT:
204+
case spv::Op::OpAtomicSMax:
205+
case spv::Op::OpAtomicUMax:
206+
case spv::Op::OpAtomicFMaxEXT:
207+
case spv::Op::OpAtomicAnd:
208+
case spv::Op::OpAtomicOr:
209+
case spv::Op::OpAtomicXor:
210+
data_type = inst->type_id();
211+
break;
212+
case spv::Op::OpAtomicFlagTestAndSet:
213+
case spv::Op::OpAtomicFlagClear:
214+
return _.diag(SPV_ERROR_INVALID_ID, inst)
215+
<< "Untyped pointers are not supported by atomic flag "
216+
"instructions";
217+
break;
218+
case spv::Op::OpAtomicStore:
219+
data_type = _.FindDef(inst->GetOperandAs<uint32_t>(3))->type_id();
220+
break;
221+
default:
222+
break;
223+
}
187224
}
188225

189226
// Can't use result_type because OpAtomicStore doesn't have a result

source/val/validate_builtins.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,16 @@ spv_result_t GetUnderlyingType(ValidationState_t& _,
9797
spv::StorageClass GetStorageClass(const Instruction& inst) {
9898
switch (inst.opcode()) {
9999
case spv::Op::OpTypePointer:
100+
case spv::Op::OpTypeUntypedPointerKHR:
100101
case spv::Op::OpTypeForwardPointer: {
101102
return spv::StorageClass(inst.word(2));
102103
}
103104
case spv::Op::OpVariable: {
104105
return spv::StorageClass(inst.word(3));
105106
}
107+
case spv::Op::OpUntypedVariableKHR: {
108+
return spv::StorageClass(inst.word(4));
109+
}
106110
case spv::Op::OpGenericCastToPtrExplicit: {
107111
return spv::StorageClass(inst.word(4));
108112
}

source/val/validate_cfg.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ spv_result_t ValidateReturnValue(ValidationState_t& _,
250250
}
251251

252252
if (_.addressing_model() == spv::AddressingModel::Logical &&
253-
spv::Op::OpTypePointer == value_type->opcode() &&
253+
(spv::Op::OpTypePointer == value_type->opcode() ||
254+
spv::Op::OpTypeUntypedPointerKHR == value_type->opcode()) &&
254255
!_.features().variable_pointers && !_.options()->relax_logical_pointer) {
255256
return _.diag(SPV_ERROR_INVALID_ID, inst)
256257
<< "OpReturnValue value's type <id> "

source/val/validate_constants.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ bool IsTypeNullable(const std::vector<uint32_t>& instruction,
324324
}
325325
return true;
326326
}
327+
case spv::Op::OpTypeUntypedPointerKHR:
327328
case spv::Op::OpTypePointer:
328329
if (spv::StorageClass(instruction[2]) ==
329330
spv::StorageClass::PhysicalStorageBuffer) {

0 commit comments

Comments
 (0)