Updated spirv-tools.

This commit is contained in:
Бранимир Караџић 2023-12-22 18:15:36 -08:00
parent 371ec431ca
commit 1fc080a8f7
14 changed files with 97 additions and 178 deletions

View File

@ -1 +1 @@
"v2023.5", "SPIRV-Tools v2023.5 v2023.5.rc1-29-g40753f37"
"v2023.6", "SPIRV-Tools v2023.6 v2023.6.rc1-1-g6a47300f"

View File

@ -43,7 +43,7 @@ static const spv::Capability pygen_variable_caps_IntegerFunctions2INTEL[] = {spv
static const spv::Capability pygen_variable_caps_Kernel[] = {spv::Capability::Kernel};
static const spv::Capability pygen_variable_caps_KernelImageQuery[] = {spv::Capability::Kernel, spv::Capability::ImageQuery};
static const spv::Capability pygen_variable_caps_LiteralSampler[] = {spv::Capability::LiteralSampler};
static const spv::Capability pygen_variable_caps_LongConstantCompositeINTEL[] = {spv::Capability::LongConstantCompositeINTEL};
static const spv::Capability pygen_variable_caps_LongCompositesINTEL[] = {spv::Capability::LongCompositesINTEL};
static const spv::Capability pygen_variable_caps_Matrix[] = {spv::Capability::Matrix};
static const spv::Capability pygen_variable_caps_MemoryAccessAliasingINTEL[] = {spv::Capability::MemoryAccessAliasingINTEL};
static const spv::Capability pygen_variable_caps_MeshShadingEXT[] = {spv::Capability::MeshShadingEXT};
@ -826,9 +826,10 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
{"RayQueryGetIntersectionWorldToObjectKHR", spv::Op::OpRayQueryGetIntersectionWorldToObjectKHR, 1, pygen_variable_caps_RayQueryKHR, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_ray_query, 0xffffffffu, 0xffffffffu},
{"AtomicFAddEXT", spv::Op::OpAtomicFAddEXT, 3, pygen_variable_caps_AtomicFloat16AddEXTAtomicFloat32AddEXTAtomicFloat64AddEXT, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float_add, 0xffffffffu, 0xffffffffu},
{"TypeBufferSurfaceINTEL", spv::Op::OpTypeBufferSurfaceINTEL, 1, pygen_variable_caps_VectorComputeINTEL, 2, {SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ACCESS_QUALIFIER}, 1, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"TypeStructContinuedINTEL", spv::Op::OpTypeStructContinuedINTEL, 1, pygen_variable_caps_LongConstantCompositeINTEL, 1, {SPV_OPERAND_TYPE_VARIABLE_ID}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"ConstantCompositeContinuedINTEL", spv::Op::OpConstantCompositeContinuedINTEL, 1, pygen_variable_caps_LongConstantCompositeINTEL, 1, {SPV_OPERAND_TYPE_VARIABLE_ID}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"SpecConstantCompositeContinuedINTEL", spv::Op::OpSpecConstantCompositeContinuedINTEL, 1, pygen_variable_caps_LongConstantCompositeINTEL, 1, {SPV_OPERAND_TYPE_VARIABLE_ID}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"TypeStructContinuedINTEL", spv::Op::OpTypeStructContinuedINTEL, 1, pygen_variable_caps_LongCompositesINTEL, 1, {SPV_OPERAND_TYPE_VARIABLE_ID}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"ConstantCompositeContinuedINTEL", spv::Op::OpConstantCompositeContinuedINTEL, 1, pygen_variable_caps_LongCompositesINTEL, 1, {SPV_OPERAND_TYPE_VARIABLE_ID}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"SpecConstantCompositeContinuedINTEL", spv::Op::OpSpecConstantCompositeContinuedINTEL, 1, pygen_variable_caps_LongCompositesINTEL, 1, {SPV_OPERAND_TYPE_VARIABLE_ID}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"CompositeConstructContinuedINTEL", spv::Op::OpCompositeConstructContinuedINTEL, 1, pygen_variable_caps_LongCompositesINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"ConvertFToBF16INTEL", spv::Op::OpConvertFToBF16INTEL, 1, pygen_variable_caps_BFloat16ConversionINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"ConvertBF16ToFINTEL", spv::Op::OpConvertBF16ToFINTEL, 1, pygen_variable_caps_BFloat16ConversionINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
{"ControlBarrierArriveINTEL", spv::Op::OpControlBarrierArriveINTEL, 1, pygen_variable_caps_SplitBarrierINTEL, 3, {SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},

File diff suppressed because one or more lines are too long

View File

@ -56,7 +56,7 @@ kSPV_INTEL_global_variable_host_access,
kSPV_INTEL_inline_assembly,
kSPV_INTEL_io_pipes,
kSPV_INTEL_kernel_attributes,
kSPV_INTEL_long_constant_composite,
kSPV_INTEL_long_composites,
kSPV_INTEL_loop_fuse,
kSPV_INTEL_media_block_io,
kSPV_INTEL_memory_access_aliasing,

View File

@ -19,6 +19,7 @@ static const spv::Capability pygen_variable_caps_FPFastMathModeINTEL[] = {spv::C
static const spv::Capability pygen_variable_caps_FPGAArgumentInterfacesINTEL[] = {spv::Capability::FPGAArgumentInterfacesINTEL};
static const spv::Capability pygen_variable_caps_FPGABufferLocationINTEL[] = {spv::Capability::FPGABufferLocationINTEL};
static const spv::Capability pygen_variable_caps_FPGAClusterAttributesINTEL[] = {spv::Capability::FPGAClusterAttributesINTEL};
static const spv::Capability pygen_variable_caps_FPGAClusterAttributesV2INTEL[] = {spv::Capability::FPGAClusterAttributesV2INTEL};
static const spv::Capability pygen_variable_caps_FPGADSPControlINTEL[] = {spv::Capability::FPGADSPControlINTEL};
static const spv::Capability pygen_variable_caps_FPGAInvocationPipeliningAttributesINTEL[] = {spv::Capability::FPGAInvocationPipeliningAttributesINTEL};
static const spv::Capability pygen_variable_caps_FPGAKernelAttributesINTEL[] = {spv::Capability::FPGAKernelAttributesINTEL};
@ -193,7 +194,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_INTEL_global_variable_h
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_inline_assembly[] = {spvtools::Extension::kSPV_INTEL_inline_assembly};
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_io_pipes[] = {spvtools::Extension::kSPV_INTEL_io_pipes};
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_kernel_attributes[] = {spvtools::Extension::kSPV_INTEL_kernel_attributes};
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_long_constant_composite[] = {spvtools::Extension::kSPV_INTEL_long_constant_composite};
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_long_composites[] = {spvtools::Extension::kSPV_INTEL_long_composites};
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_loop_fuse[] = {spvtools::Extension::kSPV_INTEL_loop_fuse};
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_media_block_io[] = {spvtools::Extension::kSPV_INTEL_media_block_io};
static const spvtools::Extension pygen_variable_exts_SPV_INTEL_memory_access_aliasing[] = {spvtools::Extension::kSPV_INTEL_memory_access_aliasing};
@ -888,6 +889,7 @@ static const spv_operand_desc_t pygen_variable_DecorationEntries[] = {
{"SingleElementVectorINTEL", 6085, 1, pygen_variable_caps_VectorComputeINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"VectorComputeCallableFunctionINTEL", 6087, 1, pygen_variable_caps_VectorComputeINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"MediaBlockIOINTEL", 6140, 1, pygen_variable_caps_VectorComputeINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"StallFreeINTEL", 6151, 1, pygen_variable_caps_FPGAClusterAttributesV2INTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
{"FPMaxErrorDecorationINTEL", 6170, 1, pygen_variable_caps_FPMaxErrorINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_FLOAT}, 0xffffffffu, 0xffffffffu},
{"LatencyControlLabelINTEL", 6172, 1, pygen_variable_caps_FPGALatencyControlINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
{"LatencyControlConstraintINTEL", 6173, 1, pygen_variable_caps_FPGALatencyControlINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
@ -1313,12 +1315,13 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
{"GroupNonUniformRotateKHR", 6026, 1, pygen_variable_caps_GroupNonUniform, 1, pygen_variable_exts_SPV_KHR_subgroup_rotate, {}, 0xffffffffu, 0xffffffffu},
{"AtomicFloat32AddEXT", 6033, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float_add, {}, 0xffffffffu, 0xffffffffu},
{"AtomicFloat64AddEXT", 6034, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float_add, {}, 0xffffffffu, 0xffffffffu},
{"LongConstantCompositeINTEL", 6089, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_long_constant_composite, {}, 0xffffffffu, 0xffffffffu},
{"LongCompositesINTEL", 6089, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_long_composites, {}, 0xffffffffu, 0xffffffffu},
{"OptNoneINTEL", 6094, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_optnone, {}, 0xffffffffu, 0xffffffffu},
{"AtomicFloat16AddEXT", 6095, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float16_add, {}, 0xffffffffu, 0xffffffffu},
{"DebugInfoModuleINTEL", 6114, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_debug_module, {}, 0xffffffffu, 0xffffffffu},
{"BFloat16ConversionINTEL", 6115, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_bfloat16_conversion, {}, 0xffffffffu, 0xffffffffu},
{"SplitBarrierINTEL", 6141, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_split_barrier, {}, 0xffffffffu, 0xffffffffu},
{"FPGAClusterAttributesV2INTEL", 6150, 1, pygen_variable_caps_FPGAClusterAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_fpga_cluster_attributes, {}, 0xffffffffu, 0xffffffffu},
{"FPGAKernelAttributesv2INTEL", 6161, 1, pygen_variable_caps_FPGAKernelAttributesINTEL, 1, pygen_variable_exts_SPV_INTEL_kernel_attributes, {}, 0xffffffffu, 0xffffffffu},
{"FPMaxErrorINTEL", 6169, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_fp_max_error, {}, 0xffffffffu, 0xffffffffu},
{"FPGALatencyControlINTEL", 6171, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_fpga_latency_control, {}, 0xffffffffu, 0xffffffffu},

View File

@ -73,81 +73,11 @@ static const int kInstCommonOutShaderId = 1;
// which generated the validation error.
static const int kInstCommonOutInstructionIdx = 2;
// This is the stage which generated the validation error. This word is used
// to determine the contents of the next two words in the record.
// 0:Vert, 1:TessCtrl, 2:TessEval, 3:Geom, 4:Frag, 5:Compute
static const int kInstCommonOutStageIdx = 3;
static const int kInstCommonOutCnt = 4;
// Stage-specific Stream Record Offsets
//
// Each stage will contain different values in the next set of words of the
// record used to identify which instantiation of the shader generated the
// validation error.
//
// Vertex Shader Output Record Offsets
static const int kInstVertOutVertexIndex = kInstCommonOutCnt;
static const int kInstVertOutInstanceIndex = kInstCommonOutCnt + 1;
static const int kInstVertOutUnused = kInstCommonOutCnt + 2;
// Frag Shader Output Record Offsets
static const int kInstFragOutFragCoordX = kInstCommonOutCnt;
static const int kInstFragOutFragCoordY = kInstCommonOutCnt + 1;
static const int kInstFragOutUnused = kInstCommonOutCnt + 2;
// Compute Shader Output Record Offsets
static const int kInstCompOutGlobalInvocationIdX = kInstCommonOutCnt;
static const int kInstCompOutGlobalInvocationIdY = kInstCommonOutCnt + 1;
static const int kInstCompOutGlobalInvocationIdZ = kInstCommonOutCnt + 2;
// Tessellation Control Shader Output Record Offsets
static const int kInstTessCtlOutInvocationId = kInstCommonOutCnt;
static const int kInstTessCtlOutPrimitiveId = kInstCommonOutCnt + 1;
static const int kInstTessCtlOutUnused = kInstCommonOutCnt + 2;
// Tessellation Eval Shader Output Record Offsets
static const int kInstTessEvalOutPrimitiveId = kInstCommonOutCnt;
static const int kInstTessEvalOutTessCoordU = kInstCommonOutCnt + 1;
static const int kInstTessEvalOutTessCoordV = kInstCommonOutCnt + 2;
// Geometry Shader Output Record Offsets
static const int kInstGeomOutPrimitiveId = kInstCommonOutCnt;
static const int kInstGeomOutInvocationId = kInstCommonOutCnt + 1;
static const int kInstGeomOutUnused = kInstCommonOutCnt + 2;
// Ray Tracing Shader Output Record Offsets
static const int kInstRayTracingOutLaunchIdX = kInstCommonOutCnt;
static const int kInstRayTracingOutLaunchIdY = kInstCommonOutCnt + 1;
static const int kInstRayTracingOutLaunchIdZ = kInstCommonOutCnt + 2;
// Mesh Shader Output Record Offsets
static const int kInstMeshOutGlobalInvocationIdX = kInstCommonOutCnt;
static const int kInstMeshOutGlobalInvocationIdY = kInstCommonOutCnt + 1;
static const int kInstMeshOutGlobalInvocationIdZ = kInstCommonOutCnt + 2;
// Task Shader Output Record Offsets
static const int kInstTaskOutGlobalInvocationIdX = kInstCommonOutCnt;
static const int kInstTaskOutGlobalInvocationIdY = kInstCommonOutCnt + 1;
static const int kInstTaskOutGlobalInvocationIdZ = kInstCommonOutCnt + 2;
// Size of Common and Stage-specific Members
static const int kInstStageOutCnt = kInstCommonOutCnt + 3;
// Debug Buffer Bindings
//
// These are the bindings for the different buffers which are
// read or written by the instrumentation passes.
//
// This is the output buffer written by InstBindlessCheckPass,
// InstBuffAddrCheckPass, and possibly other future validations.
static const int kDebugOutputBindingStream = 0;
// The binding for the input buffer read by InstBindlessCheckPass.
static const int kDebugInputBindingBindless = 1;
// The binding for the input buffer read by InstBuffAddrCheckPass.
static const int kDebugInputBindingBuffAddr = 2;
// This is the output buffer written by InstDebugPrintfPass.
static const int kDebugOutputPrintfStream = 3;

View File

@ -176,8 +176,9 @@ Instruction* FoldSpecConstantOpAndCompositePass::FoldWithInstructionFolder(
Instruction* new_const_inst =
context()->get_instruction_folder().FoldInstructionToConstant(
inst.get(), identity_map);
assert(new_const_inst != nullptr &&
"Failed to fold instruction that must be folded.");
// new_const_inst == null indicates we cannot fold this spec constant
if (!new_const_inst) return nullptr;
// Get the instruction before |pos| to insert after. |pos| cannot be the
// first instruction in the list because its type has to come first.

View File

@ -29,7 +29,7 @@ namespace opt {
class InstBindlessCheckPass : public InstrumentPass {
public:
InstBindlessCheckPass(uint32_t shader_id)
: InstrumentPass(0, shader_id, true) {}
: InstrumentPass(0, shader_id, true, true) {}
~InstBindlessCheckPass() override = default;

View File

@ -29,9 +29,10 @@ namespace opt {
class InstBuffAddrCheckPass : public InstrumentPass {
public:
// For test harness only
InstBuffAddrCheckPass() : InstrumentPass(0, 23) {}
InstBuffAddrCheckPass() : InstrumentPass(0, 23, false, true) {}
// For all other interfaces
InstBuffAddrCheckPass(uint32_t shader_id) : InstrumentPass(0, shader_id) {}
InstBuffAddrCheckPass(uint32_t shader_id)
: InstrumentPass(0, shader_id, false, true) {}
~InstBuffAddrCheckPass() override = default;

View File

@ -138,7 +138,7 @@ void InstDebugPrintfPass::GenOutputValues(Instruction* val_inst,
}
void InstDebugPrintfPass::GenOutputCode(
Instruction* printf_inst, uint32_t stage_idx,
Instruction* printf_inst,
std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
BasicBlock* back_blk_ptr = &*new_blocks->back();
InstructionBuilder builder(
@ -168,14 +168,14 @@ void InstDebugPrintfPass::GenOutputCode(
});
GenDebugStreamWrite(
builder.GetUintConstantId(shader_id_),
builder.GetUintConstantId(uid2offset_[printf_inst->unique_id()]),
GenStageInfo(stage_idx, &builder), val_ids, &builder);
builder.GetUintConstantId(uid2offset_[printf_inst->unique_id()]), val_ids,
&builder);
context()->KillInst(printf_inst);
}
void InstDebugPrintfPass::GenDebugPrintfCode(
BasicBlock::iterator ref_inst_itr,
UptrVectorIterator<BasicBlock> ref_block_itr, uint32_t stage_idx,
UptrVectorIterator<BasicBlock> ref_block_itr,
std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
// If not DebugPrintf OpExtInst, return.
Instruction* printf_inst = &*ref_inst_itr;
@ -191,7 +191,7 @@ void InstDebugPrintfPass::GenDebugPrintfCode(
MovePreludeCode(ref_inst_itr, ref_block_itr, &new_blk_ptr);
new_blocks->push_back(std::move(new_blk_ptr));
// Generate instructions to output printf args to printf buffer
GenOutputCode(printf_inst, stage_idx, new_blocks);
GenOutputCode(printf_inst, new_blocks);
// Caller expects at least two blocks with last block containing remaining
// code, so end block after instrumentation, create remainder block, and
// branch to it
@ -301,8 +301,7 @@ uint32_t InstDebugPrintfPass::GetStreamWriteFunctionId(uint32_t param_cnt) {
enum {
kShaderId = 0,
kInstructionIndex = 1,
kStageInfo = 2,
kFirstParam = 3,
kFirstParam = 2,
};
// Total param count is common params plus validation-specific
// params
@ -312,12 +311,9 @@ uint32_t InstDebugPrintfPass::GetStreamWriteFunctionId(uint32_t param_cnt) {
analysis::TypeManager* type_mgr = context()->get_type_mgr();
const analysis::Type* uint_type = GetInteger(32, false);
const analysis::Vector v4uint(uint_type, 4);
const analysis::Type* v4uint_type = type_mgr->GetRegisteredType(&v4uint);
std::vector<const analysis::Type*> param_types(kFirstParam + param_cnt,
uint_type);
param_types[kStageInfo] = v4uint_type;
std::unique_ptr<Function> output_func = StartFunction(
param2output_func_id_[param_cnt], type_mgr->GetVoidType(), param_types);
@ -330,8 +326,8 @@ uint32_t InstDebugPrintfPass::GetStreamWriteFunctionId(uint32_t param_cnt) {
context(), &*new_blk_ptr,
IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
// Gen test if debug output buffer size will not be exceeded.
const uint32_t val_spec_offset = kInstStageOutCnt;
const uint32_t obuf_record_sz = val_spec_offset + param_cnt;
const uint32_t first_param_offset = kInstCommonOutInstructionIdx + 1;
const uint32_t obuf_record_sz = first_param_offset + param_cnt;
const uint32_t buf_id = GetOutputBufferId();
const uint32_t buf_uint_ptr_id = GetOutputBufferPtrId();
Instruction* obuf_curr_sz_ac_inst = builder.AddAccessChain(
@ -382,16 +378,9 @@ uint32_t InstDebugPrintfPass::GetStreamWriteFunctionId(uint32_t param_cnt) {
// Store Instruction Idx
GenDebugOutputFieldCode(obuf_curr_sz_id, kInstCommonOutInstructionIdx,
param_ids[kInstructionIndex], &builder);
// Store stage info. Stage Idx + 3 words of stage-specific data.
for (uint32_t i = 0; i < 4; ++i) {
Instruction* field =
builder.AddCompositeExtract(GetUintId(), param_ids[kStageInfo], {i});
GenDebugOutputFieldCode(obuf_curr_sz_id, kInstCommonOutStageIdx + i,
field->result_id(), &builder);
}
// Gen writes of validation specific data
for (uint32_t i = 0; i < param_cnt; ++i) {
GenDebugOutputFieldCode(obuf_curr_sz_id, val_spec_offset + i,
GenDebugOutputFieldCode(obuf_curr_sz_id, first_param_offset + i,
param_ids[kFirstParam + i], &builder);
}
// Close write block and gen merge block
@ -416,12 +405,12 @@ uint32_t InstDebugPrintfPass::GetStreamWriteFunctionId(uint32_t param_cnt) {
}
void InstDebugPrintfPass::GenDebugStreamWrite(
uint32_t shader_id, uint32_t instruction_idx_id, uint32_t stage_info_id,
uint32_t shader_id, uint32_t instruction_idx_id,
const std::vector<uint32_t>& validation_ids, InstructionBuilder* builder) {
// Call debug output function. Pass func_idx, instruction_idx and
// validation ids as args.
uint32_t val_id_cnt = static_cast<uint32_t>(validation_ids.size());
std::vector<uint32_t> args = {shader_id, instruction_idx_id, stage_info_id};
std::vector<uint32_t> args = {shader_id, instruction_idx_id};
(void)args.insert(args.end(), validation_ids.begin(), validation_ids.end());
(void)builder->AddFunctionCall(GetVoidId(),
GetStreamWriteFunctionId(val_id_cnt), args);
@ -455,10 +444,10 @@ Pass::Status InstDebugPrintfPass::ProcessImpl() {
// Perform printf instrumentation on each entry point function in module
InstProcessFunction pfn =
[this](BasicBlock::iterator ref_inst_itr,
UptrVectorIterator<BasicBlock> ref_block_itr, uint32_t stage_idx,
UptrVectorIterator<BasicBlock> ref_block_itr,
[[maybe_unused]] uint32_t stage_idx,
std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
return GenDebugPrintfCode(ref_inst_itr, ref_block_itr, stage_idx,
new_blocks);
return GenDebugPrintfCode(ref_inst_itr, ref_block_itr, new_blocks);
};
(void)InstProcessEntryPointCallTree(pfn);
// Remove DebugPrintf OpExtInstImport instruction

View File

@ -28,10 +28,10 @@ namespace opt {
class InstDebugPrintfPass : public InstrumentPass {
public:
// For test harness only
InstDebugPrintfPass() : InstrumentPass(7, 23) {}
InstDebugPrintfPass() : InstrumentPass(7, 23, false, false) {}
// For all other interfaces
InstDebugPrintfPass(uint32_t desc_set, uint32_t shader_id)
: InstrumentPass(desc_set, shader_id) {}
: InstrumentPass(desc_set, shader_id, false, false) {}
~InstDebugPrintfPass() override = default;
@ -52,9 +52,7 @@ class InstDebugPrintfPass : public InstrumentPass {
// validation and write a record to the end of the stream, if enough space
// in the buffer remains. The record will contain the index of the function
// and instruction within that function |func_idx, instruction_idx| which
// generated the record. It will also contain additional information to
// identify the instance of the shader, depending on the stage |stage_idx|
// of the shader. Finally, the record will contain validation-specific
// generated the record. Finally, the record will contain validation-specific
// data contained in |validation_ids| which will identify the validation
// error as well as the values involved in the error.
//
@ -83,9 +81,6 @@ class InstDebugPrintfPass : public InstrumentPass {
// Record Size
// Shader ID
// Instruction Index
// Stage
// Stage-specific Word 0
// Stage-specific Word 1
// ...
// Validation Error Code
// Validation-specific Word 0
@ -93,8 +88,8 @@ class InstDebugPrintfPass : public InstrumentPass {
// Validation-specific Word 2
// ...
//
// Each record consists of three subsections: members common across all
// validation, members specific to the stage, and members specific to a
// Each record consists of two subsections: members common across all
// validation and members specific to a
// validation.
//
// The Record Size is the number of 32-bit words in the record, including
@ -106,18 +101,6 @@ class InstDebugPrintfPass : public InstrumentPass {
// The Instruction Index is the position of the instruction within the
// SPIR-V file which is in error.
//
// The Stage is the pipeline stage which has generated the error as defined
// by the SpvExecutionModel_ enumeration. This is used to interpret the
// following Stage-specific words.
//
// The Stage-specific Words identify which invocation of the shader generated
// the error. Every stage will write a fixed number of words. Vertex shaders
// will write the Vertex and Instance ID. Fragment shaders will write
// FragCoord.xy. Compute shaders will write the GlobalInvocation ID.
// The tessellation eval shader will write the Primitive ID and TessCoords.uv.
// The tessellation control shader and geometry shader will write the
// Primitive ID and Invocation ID.
//
// The Validation Error Code specifies the exact error which has occurred.
// These are enumerated with the kInstError* static consts. This allows
// multiple validation layers to use the same, single output buffer.
@ -131,7 +114,6 @@ class InstDebugPrintfPass : public InstrumentPass {
// before writing, the size of the debug out buffer can be used by the
// validation layer to control the number of error records that are written.
void GenDebugStreamWrite(uint32_t shader_id, uint32_t instruction_idx_id,
uint32_t stage_info_id,
const std::vector<uint32_t>& validation_ids,
InstructionBuilder* builder);
@ -144,7 +126,7 @@ class InstDebugPrintfPass : public InstrumentPass {
// If |ref_inst_itr| is an OpDebugPrintf, return in |new_blocks| the result
// of replacing it with buffer write instructions within its block at
// |ref_block_itr|. The instructions write a record to the printf
// output buffer stream including |function_idx, instruction_idx, stage_idx|
// output buffer stream including |function_idx, instruction_idx|
// and removes the OpDebugPrintf. The block at |ref_block_itr| can just be
// replaced with the block in |new_blocks|. Besides the buffer writes, this
// block will comprise all instructions preceding and following
@ -162,7 +144,6 @@ class InstDebugPrintfPass : public InstrumentPass {
// DebugPrintf.
void GenDebugPrintfCode(BasicBlock::iterator ref_inst_itr,
UptrVectorIterator<BasicBlock> ref_block_itr,
uint32_t stage_idx,
std::vector<std::unique_ptr<BasicBlock>>* new_blocks);
// Generate a sequence of uint32 instructions in |builder| (if necessary)
@ -175,7 +156,7 @@ class InstDebugPrintfPass : public InstrumentPass {
// Generate instructions to write a record containing the operands of
// |printf_inst| arguments to printf buffer, adding new code to the end of
// the last block in |new_blocks|. Kill OpDebugPrintf instruction.
void GenOutputCode(Instruction* printf_inst, uint32_t stage_idx,
void GenOutputCode(Instruction* printf_inst,
std::vector<std::unique_ptr<BasicBlock>>* new_blocks);
// Set the name for a function or global variable, names will be

View File

@ -213,14 +213,14 @@ uint32_t InstrumentPass::GenStageInfo(uint32_t stage_idx,
load_id = GenVarLoad(
context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::InvocationId)),
builder);
ids[2] = load_id;
ids[2] = GenUintCastCode(load_id, builder);
} break;
case spv::ExecutionModel::TessellationControl: {
// Load and store InvocationId and PrimitiveId
uint32_t load_id = GenVarLoad(
context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::InvocationId)),
builder);
ids[1] = load_id;
ids[1] = GenUintCastCode(load_id, builder);
load_id = GenVarLoad(
context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::PrimitiveId)),
builder);
@ -653,44 +653,50 @@ bool InstrumentPass::InstProcessCallTreeFromRoots(InstProcessFunction& pfn,
}
bool InstrumentPass::InstProcessEntryPointCallTree(InstProcessFunction& pfn) {
// Make sure all entry points have the same execution model. Do not
// instrument if they do not.
// TODO(greg-lunarg): Handle mixed stages. Technically, a shader module
// can contain entry points with different execution models, although
// such modules will likely be rare as GLSL and HLSL are geared toward
// one model per module. In such cases we will need
// to clone any functions which are in the call trees of entrypoints
// with differing execution models.
spv::ExecutionModel stage = context()->GetStage();
// Check for supported stages
if (stage != spv::ExecutionModel::Vertex &&
stage != spv::ExecutionModel::Fragment &&
stage != spv::ExecutionModel::Geometry &&
stage != spv::ExecutionModel::GLCompute &&
stage != spv::ExecutionModel::TessellationControl &&
stage != spv::ExecutionModel::TessellationEvaluation &&
stage != spv::ExecutionModel::TaskNV &&
stage != spv::ExecutionModel::MeshNV &&
stage != spv::ExecutionModel::RayGenerationNV &&
stage != spv::ExecutionModel::IntersectionNV &&
stage != spv::ExecutionModel::AnyHitNV &&
stage != spv::ExecutionModel::ClosestHitNV &&
stage != spv::ExecutionModel::MissNV &&
stage != spv::ExecutionModel::CallableNV &&
stage != spv::ExecutionModel::TaskEXT &&
stage != spv::ExecutionModel::MeshEXT) {
if (consumer()) {
std::string message = "Stage not supported by instrumentation";
consumer()(SPV_MSG_ERROR, 0, {0, 0, 0}, message.c_str());
uint32_t stage_id;
if (use_stage_info_) {
// Make sure all entry points have the same execution model. Do not
// instrument if they do not.
// TODO(greg-lunarg): Handle mixed stages. Technically, a shader module
// can contain entry points with different execution models, although
// such modules will likely be rare as GLSL and HLSL are geared toward
// one model per module. In such cases we will need
// to clone any functions which are in the call trees of entrypoints
// with differing execution models.
spv::ExecutionModel stage = context()->GetStage();
// Check for supported stages
if (stage != spv::ExecutionModel::Vertex &&
stage != spv::ExecutionModel::Fragment &&
stage != spv::ExecutionModel::Geometry &&
stage != spv::ExecutionModel::GLCompute &&
stage != spv::ExecutionModel::TessellationControl &&
stage != spv::ExecutionModel::TessellationEvaluation &&
stage != spv::ExecutionModel::TaskNV &&
stage != spv::ExecutionModel::MeshNV &&
stage != spv::ExecutionModel::RayGenerationNV &&
stage != spv::ExecutionModel::IntersectionNV &&
stage != spv::ExecutionModel::AnyHitNV &&
stage != spv::ExecutionModel::ClosestHitNV &&
stage != spv::ExecutionModel::MissNV &&
stage != spv::ExecutionModel::CallableNV &&
stage != spv::ExecutionModel::TaskEXT &&
stage != spv::ExecutionModel::MeshEXT) {
if (consumer()) {
std::string message = "Stage not supported by instrumentation";
consumer()(SPV_MSG_ERROR, 0, {0, 0, 0}, message.c_str());
}
return false;
}
return false;
stage_id = static_cast<uint32_t>(stage);
} else {
stage_id = 0;
}
// Add together the roots of all entry points
std::queue<uint32_t> roots;
for (auto& e : get_module()->entry_points()) {
roots.push(e.GetSingleWordInOperand(kEntryPointFunctionIdInIdx));
}
bool modified = InstProcessCallTreeFromRoots(pfn, &roots, uint32_t(stage));
bool modified = InstProcessCallTreeFromRoots(pfn, &roots, stage_id);
return modified;
}

View File

@ -77,12 +77,13 @@ class InstrumentPass : public Pass {
// set |desc_set| for debug input and output buffers and writes |shader_id|
// into debug output records. |opt_direct_reads| indicates that the pass
// will see direct input buffer reads and should prepare to optimize them.
InstrumentPass(uint32_t desc_set, uint32_t shader_id,
bool opt_direct_reads = false)
InstrumentPass(uint32_t desc_set, uint32_t shader_id, bool opt_direct_reads,
bool use_stage_info)
: Pass(),
desc_set_(desc_set),
shader_id_(shader_id),
opt_direct_reads_(opt_direct_reads) {}
opt_direct_reads_(opt_direct_reads),
use_stage_info_(use_stage_info) {}
// Initialize state for instrumentation of module.
void InitializeInstrument();
@ -312,7 +313,11 @@ class InstrumentPass : public Pass {
// Optimize direct debug input buffer reads. Specifically, move all such
// reads with constant args to first block and reuse them.
bool opt_direct_reads_{false};
const bool opt_direct_reads_;
// Set true if the instrumentation needs to know the current stage.
// Note that this does not work with multi-stage modules.
const bool use_stage_info_;
};
} // namespace opt

View File

@ -560,7 +560,7 @@ bool Optimizer::RegisterPassFromFlag(const std::string& flag) {
"--switch-descriptorset requires a from:to argument.");
return false;
}
uint32_t from_set, to_set;
uint32_t from_set = 0, to_set = 0;
const char* start = pass_args.data();
const char* end = pass_args.data() + pass_args.size();