MCPcopy Create free account
hub / github.com/KhronosGroup/SPIRV-Tools / assignStructMemberOffsets

Method assignStructMemberOffsets

source/opt/struct_packing_pass.cpp:409–479  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

407}
408
409Pass::Status StructPackingPass::assignStructMemberOffsets(
410 uint32_t structIdToPack,
411 const std::vector<const analysis::Type*>& structMemberTypes) {
412 // Returns true if the specified instruction is a OpMemberDecorate for the
413 // struct we're looking for with an offset decoration
414 auto isMemberOffsetDecoration =
415 [structIdToPack](const Instruction& instr) -> bool {
416 return instr.opcode() == spv::Op::OpMemberDecorate &&
417 instr.GetOperand(0).AsId() == structIdToPack &&
418 static_cast<spv::Decoration>(instr.GetOperand(2).words[0]) ==
419 spv::Decoration::Offset;
420 };
421
422 bool modified = false;
423
424 // Find and re-assign all member offset decorations
425 for (auto it = context()->module()->annotation_begin(),
426 itEnd = context()->module()->annotation_end();
427 it != itEnd; ++it) {
428 if (isMemberOffsetDecoration(*it)) {
429 // Found first member decoration with offset, we expect all other
430 // offsets right after the first one
431 uint32_t prevMemberIndex = 0;
432 uint32_t currentOffset = 0;
433 uint32_t padAlignment = 1;
434 do {
435 const uint32_t memberIndex = it->GetOperand(1).words[0];
436 if (memberIndex < prevMemberIndex) {
437 // Failure: we expect all members to appear in consecutive order
438 return Status::Failure;
439 }
440
441 // Apply alignment rules to current offset
442 const analysis::Type& memberType = *structMemberTypes[memberIndex];
443 uint32_t packedAlignment = getPackedAlignment(memberType);
444 uint32_t packedSize = getPackedSize(memberType);
445
446 if (isPackingHlsl(packingRules_)) {
447 // If a member crosses vec4 boundaries, alignment is size of vec4
448 if (currentOffset / 16 != (currentOffset + packedSize - 1) / 16)
449 packedAlignment = std::max<uint32_t>(packedAlignment, 16u);
450 }
451
452 const uint32_t alignment =
453 std::max<uint32_t>(packedAlignment, padAlignment);
454 currentOffset = alignPow2(currentOffset, alignment);
455 padAlignment = getPadAlignment(memberType, packedAlignment);
456
457 // Override packed offset in instruction
458 if (it->GetOperand(3).words[0] < currentOffset) {
459 // Failure: packing resulted in higher offset for member than
460 // previously generated
461 return Status::Failure;
462 }
463
464 it->GetOperand(3).words[0] = currentOffset;
465 modified = true;
466

Callers

nothing calls this directly

Calls 8

isPackingHlslFunction · 0.85
alignPow2Function · 0.85
getPadAlignmentFunction · 0.85
AsIdMethod · 0.80
opcodeMethod · 0.45
annotation_beginMethod · 0.45
moduleMethod · 0.45
annotation_endMethod · 0.45

Tested by

no test coverage detected