@@ -166,20 +166,17 @@ spv_result_t NumConsumedLocations(ValidationState_t& _, const Instruction* type,
166
166
}
167
167
break ;
168
168
case spv::Op::OpTypeMatrix:
169
- // Matrices consume locations equivalent to arrays.
170
- if (auto error = NumConsumedLocations (
171
- _, _.FindDef (type->GetOperandAs <uint32_t >(1 )), num_locations)) {
172
- return error;
173
- }
169
+ // Matrices consume locations equal to the underlying vector type for
170
+ // each column.
171
+ NumConsumedLocations (_, _.FindDef (type->GetOperandAs <uint32_t >(1 )),
172
+ num_locations);
174
173
*num_locations *= type->GetOperandAs <uint32_t >(2 );
175
174
break ;
176
175
case spv::Op::OpTypeArray: {
177
176
// Arrays consume locations equal to the underlying type times the number
178
177
// of elements in the vector.
179
- if (auto error = NumConsumedLocations (
180
- _, _.FindDef (type->GetOperandAs <uint32_t >(1 )), num_locations)) {
181
- return error;
182
- }
178
+ NumConsumedLocations (_, _.FindDef (type->GetOperandAs <uint32_t >(1 )),
179
+ num_locations);
183
180
bool is_int = false ;
184
181
bool is_const = false ;
185
182
uint32_t value = 0 ;
@@ -249,31 +246,10 @@ uint32_t NumConsumedComponents(ValidationState_t& _, const Instruction* type) {
249
246
NumConsumedComponents (_, _.FindDef (type->GetOperandAs <uint32_t >(1 )));
250
247
num_components *= type->GetOperandAs <uint32_t >(2 );
251
248
break ;
252
- case spv::Op::OpTypeMatrix:
253
- // Matrices consume all components of the location.
254
- // Round up to next multiple of 4.
255
- num_components =
256
- NumConsumedComponents (_, _.FindDef (type->GetOperandAs <uint32_t >(1 )));
257
- num_components *= type->GetOperandAs <uint32_t >(2 );
258
- num_components = ((num_components + 3 ) / 4 ) * 4 ;
259
- break ;
260
- case spv::Op::OpTypeArray: {
261
- // Arrays consume all components of the location.
262
- // Round up to next multiple of 4.
263
- num_components =
264
- NumConsumedComponents (_, _.FindDef (type->GetOperandAs <uint32_t >(1 )));
265
-
266
- bool is_int = false ;
267
- bool is_const = false ;
268
- uint32_t value = 0 ;
269
- // Attempt to evaluate the number of array elements.
270
- std::tie (is_int, is_const, value) =
271
- _.EvalInt32IfConst (type->GetOperandAs <uint32_t >(2 ));
272
- if (is_int && is_const) num_components *= value;
273
-
274
- num_components = ((num_components + 3 ) / 4 ) * 4 ;
275
- return num_components;
276
- }
249
+ case spv::Op::OpTypeArray:
250
+ // Skip the array.
251
+ return NumConsumedComponents (_,
252
+ _.FindDef (type->GetOperandAs <uint32_t >(1 )));
277
253
case spv::Op::OpTypePointer:
278
254
if (_.addressing_model () ==
279
255
spv::AddressingModel::PhysicalStorageBuffer64 &&
@@ -356,10 +332,9 @@ spv_result_t GetLocationsForVariable(
356
332
}
357
333
}
358
334
359
- // Vulkan 15.1.3 (Interface Matching): Tessellation control and mesh
360
- // per-vertex outputs and tessellation control, evaluation and geometry
361
- // per-vertex inputs have a layer of arraying that is not included in
362
- // interface matching.
335
+ // Vulkan 14.1.3: Tessellation control and mesh per-vertex outputs and
336
+ // tessellation control, evaluation and geometry per-vertex inputs have a
337
+ // layer of arraying that is not included in interface matching.
363
338
bool is_arrayed = false ;
364
339
switch (entry_point->GetOperandAs <spv::ExecutionModel>(0 )) {
365
340
case spv::ExecutionModel::TessellationControl:
@@ -413,33 +388,51 @@ spv_result_t GetLocationsForVariable(
413
388
414
389
const std::string storage_class = is_output ? " output" : " input" ;
415
390
if (has_location) {
391
+ auto sub_type = type;
392
+ bool is_int = false ;
393
+ bool is_const = false ;
394
+ uint32_t array_size = 1 ;
395
+ // If the variable is still arrayed, mark the locations/components per
396
+ // index.
397
+ if (type->opcode () == spv::Op::OpTypeArray) {
398
+ // Determine the array size if possible and get the element type.
399
+ std::tie (is_int, is_const, array_size) =
400
+ _.EvalInt32IfConst (type->GetOperandAs <uint32_t >(2 ));
401
+ if (!is_int || !is_const) array_size = 1 ;
402
+ auto sub_type_id = type->GetOperandAs <uint32_t >(1 );
403
+ sub_type = _.FindDef (sub_type_id);
404
+ }
405
+
416
406
uint32_t num_locations = 0 ;
417
- if (auto error = NumConsumedLocations (_, type , &num_locations))
407
+ if (auto error = NumConsumedLocations (_, sub_type , &num_locations))
418
408
return error;
419
- uint32_t num_components = NumConsumedComponents (_, type );
409
+ uint32_t num_components = NumConsumedComponents (_, sub_type );
420
410
421
- uint32_t start = location * 4 ;
422
- uint32_t end = (location + num_locations) * 4 ;
423
- if (num_components % 4 != 0 ) {
424
- start += component;
425
- end = start + num_components;
426
- }
411
+ for (uint32_t array_idx = 0 ; array_idx < array_size; ++array_idx) {
412
+ uint32_t array_location = location + (num_locations * array_idx);
413
+ uint32_t start = array_location * 4 ;
414
+ if (kMaxLocations <= start) {
415
+ // Too many locations, give up.
416
+ break ;
417
+ }
427
418
428
- if (kMaxLocations <= start) {
429
- // Too many locations, give up.
430
- return SPV_SUCCESS;
431
- }
419
+ uint32_t end = (array_location + num_locations) * 4 ;
420
+ if (num_components != 0 ) {
421
+ start += component;
422
+ end = array_location * 4 + component + num_components;
423
+ }
432
424
433
- auto locs = locations;
434
- if (has_index && index == 1 ) locs = output_index1_locations;
425
+ auto locs = locations;
426
+ if (has_index && index == 1 ) locs = output_index1_locations;
435
427
436
- for (uint32_t i = start; i < end; ++i) {
437
- if (!locs->insert (i).second ) {
438
- return _.diag (SPV_ERROR_INVALID_DATA, entry_point)
439
- << (is_output ? _.VkErrorID (8722 ) : _.VkErrorID (8721 ))
440
- << " Entry-point has conflicting " << storage_class
441
- << " location assignment at location " << i / 4 << " , component "
442
- << i % 4 ;
428
+ for (uint32_t i = start; i < end; ++i) {
429
+ if (!locs->insert (i).second ) {
430
+ return _.diag (SPV_ERROR_INVALID_DATA, entry_point)
431
+ << (is_output ? _.VkErrorID (8722 ) : _.VkErrorID (8721 ))
432
+ << " Entry-point has conflicting " << storage_class
433
+ << " location assignment at location " << i / 4
434
+ << " , component " << i % 4 ;
435
+ }
443
436
}
444
437
}
445
438
} else {
@@ -498,19 +491,38 @@ spv_result_t GetLocationsForVariable(
498
491
continue ;
499
492
}
500
493
501
- uint32_t end = (location + num_locations) * 4 ;
502
- if (num_components % 4 != 0 ) {
503
- start += component;
504
- end = location * 4 + component + num_components;
505
- }
506
-
507
- for (uint32_t l = start; l < end; ++l) {
508
- if (!locations->insert (l).second ) {
509
- return _.diag (SPV_ERROR_INVALID_DATA, entry_point)
510
- << (is_output ? _.VkErrorID (8722 ) : _.VkErrorID (8721 ))
511
- << " Entry-point has conflicting " << storage_class
512
- << " location assignment at location " << l / 4
513
- << " , component " << l % 4 ;
494
+ if (member->opcode () == spv::Op::OpTypeArray && num_components >= 1 &&
495
+ num_components < 4 ) {
496
+ // When an array has an element that takes less than a location in
497
+ // size, calculate the used locations in a strided manner.
498
+ for (uint32_t l = location; l < num_locations + location; ++l) {
499
+ for (uint32_t c = component; c < component + num_components; ++c) {
500
+ uint32_t check = 4 * l + c;
501
+ if (!locations->insert (check).second ) {
502
+ return _.diag (SPV_ERROR_INVALID_DATA, entry_point)
503
+ << (is_output ? _.VkErrorID (8722 ) : _.VkErrorID (8721 ))
504
+ << " Entry-point has conflicting " << storage_class
505
+ << " location assignment at location " << l
506
+ << " , component " << c;
507
+ }
508
+ }
509
+ }
510
+ } else {
511
+ // TODO: There is a hole here is the member is an array of 3- or
512
+ // 4-element vectors of 64-bit types.
513
+ uint32_t end = (location + num_locations) * 4 ;
514
+ if (num_components != 0 ) {
515
+ start += component;
516
+ end = location * 4 + component + num_components;
517
+ }
518
+ for (uint32_t l = start; l < end; ++l) {
519
+ if (!locations->insert (l).second ) {
520
+ return _.diag (SPV_ERROR_INVALID_DATA, entry_point)
521
+ << (is_output ? _.VkErrorID (8722 ) : _.VkErrorID (8721 ))
522
+ << " Entry-point has conflicting " << storage_class
523
+ << " location assignment at location " << l / 4
524
+ << " , component " << l % 4 ;
525
+ }
514
526
}
515
527
}
516
528
}
0 commit comments