Skip to content

Commit b5d6082

Browse files
printf: Remove stage specific info (#5495)
Remove stage specific debug info that is only needed by GPU-AV. This allows debug printfs to be used in multi-stage shader modules. Fixes #4892
1 parent e7a52b7 commit b5d6082

8 files changed

+81
-196
lines changed

include/spirv-tools/instrument.hpp

-70
Original file line numberDiff line numberDiff line change
@@ -73,81 +73,11 @@ static const int kInstCommonOutShaderId = 1;
7373
// which generated the validation error.
7474
static const int kInstCommonOutInstructionIdx = 2;
7575

76-
// This is the stage which generated the validation error. This word is used
77-
// to determine the contents of the next two words in the record.
78-
// 0:Vert, 1:TessCtrl, 2:TessEval, 3:Geom, 4:Frag, 5:Compute
79-
static const int kInstCommonOutStageIdx = 3;
80-
static const int kInstCommonOutCnt = 4;
81-
82-
// Stage-specific Stream Record Offsets
83-
//
84-
// Each stage will contain different values in the next set of words of the
85-
// record used to identify which instantiation of the shader generated the
86-
// validation error.
87-
//
88-
// Vertex Shader Output Record Offsets
89-
static const int kInstVertOutVertexIndex = kInstCommonOutCnt;
90-
static const int kInstVertOutInstanceIndex = kInstCommonOutCnt + 1;
91-
static const int kInstVertOutUnused = kInstCommonOutCnt + 2;
92-
93-
// Frag Shader Output Record Offsets
94-
static const int kInstFragOutFragCoordX = kInstCommonOutCnt;
95-
static const int kInstFragOutFragCoordY = kInstCommonOutCnt + 1;
96-
static const int kInstFragOutUnused = kInstCommonOutCnt + 2;
97-
98-
// Compute Shader Output Record Offsets
99-
static const int kInstCompOutGlobalInvocationIdX = kInstCommonOutCnt;
100-
static const int kInstCompOutGlobalInvocationIdY = kInstCommonOutCnt + 1;
101-
static const int kInstCompOutGlobalInvocationIdZ = kInstCommonOutCnt + 2;
102-
103-
// Tessellation Control Shader Output Record Offsets
104-
static const int kInstTessCtlOutInvocationId = kInstCommonOutCnt;
105-
static const int kInstTessCtlOutPrimitiveId = kInstCommonOutCnt + 1;
106-
static const int kInstTessCtlOutUnused = kInstCommonOutCnt + 2;
107-
108-
// Tessellation Eval Shader Output Record Offsets
109-
static const int kInstTessEvalOutPrimitiveId = kInstCommonOutCnt;
110-
static const int kInstTessEvalOutTessCoordU = kInstCommonOutCnt + 1;
111-
static const int kInstTessEvalOutTessCoordV = kInstCommonOutCnt + 2;
112-
113-
// Geometry Shader Output Record Offsets
114-
static const int kInstGeomOutPrimitiveId = kInstCommonOutCnt;
115-
static const int kInstGeomOutInvocationId = kInstCommonOutCnt + 1;
116-
static const int kInstGeomOutUnused = kInstCommonOutCnt + 2;
117-
118-
// Ray Tracing Shader Output Record Offsets
119-
static const int kInstRayTracingOutLaunchIdX = kInstCommonOutCnt;
120-
static const int kInstRayTracingOutLaunchIdY = kInstCommonOutCnt + 1;
121-
static const int kInstRayTracingOutLaunchIdZ = kInstCommonOutCnt + 2;
122-
123-
// Mesh Shader Output Record Offsets
124-
static const int kInstMeshOutGlobalInvocationIdX = kInstCommonOutCnt;
125-
static const int kInstMeshOutGlobalInvocationIdY = kInstCommonOutCnt + 1;
126-
static const int kInstMeshOutGlobalInvocationIdZ = kInstCommonOutCnt + 2;
127-
128-
// Task Shader Output Record Offsets
129-
static const int kInstTaskOutGlobalInvocationIdX = kInstCommonOutCnt;
130-
static const int kInstTaskOutGlobalInvocationIdY = kInstCommonOutCnt + 1;
131-
static const int kInstTaskOutGlobalInvocationIdZ = kInstCommonOutCnt + 2;
132-
133-
// Size of Common and Stage-specific Members
134-
static const int kInstStageOutCnt = kInstCommonOutCnt + 3;
135-
13676
// Debug Buffer Bindings
13777
//
13878
// These are the bindings for the different buffers which are
13979
// read or written by the instrumentation passes.
14080
//
141-
// This is the output buffer written by InstBindlessCheckPass,
142-
// InstBuffAddrCheckPass, and possibly other future validations.
143-
static const int kDebugOutputBindingStream = 0;
144-
145-
// The binding for the input buffer read by InstBindlessCheckPass.
146-
static const int kDebugInputBindingBindless = 1;
147-
148-
// The binding for the input buffer read by InstBuffAddrCheckPass.
149-
static const int kDebugInputBindingBuffAddr = 2;
150-
15181
// This is the output buffer written by InstDebugPrintfPass.
15282
static const int kDebugOutputPrintfStream = 3;
15383

source/opt/inst_bindless_check_pass.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ namespace opt {
2929
class InstBindlessCheckPass : public InstrumentPass {
3030
public:
3131
InstBindlessCheckPass(uint32_t shader_id)
32-
: InstrumentPass(0, shader_id, true) {}
32+
: InstrumentPass(0, shader_id, true, true) {}
3333

3434
~InstBindlessCheckPass() override = default;
3535

source/opt/inst_buff_addr_check_pass.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ namespace opt {
2929
class InstBuffAddrCheckPass : public InstrumentPass {
3030
public:
3131
// For test harness only
32-
InstBuffAddrCheckPass() : InstrumentPass(0, 23) {}
32+
InstBuffAddrCheckPass() : InstrumentPass(0, 23, false, true) {}
3333
// For all other interfaces
34-
InstBuffAddrCheckPass(uint32_t shader_id) : InstrumentPass(0, shader_id) {}
34+
InstBuffAddrCheckPass(uint32_t shader_id)
35+
: InstrumentPass(0, shader_id, false, true) {}
3536

3637
~InstBuffAddrCheckPass() override = default;
3738

source/opt/inst_debug_printf_pass.cpp

+14-25
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ void InstDebugPrintfPass::GenOutputValues(Instruction* val_inst,
138138
}
139139

140140
void InstDebugPrintfPass::GenOutputCode(
141-
Instruction* printf_inst, uint32_t stage_idx,
141+
Instruction* printf_inst,
142142
std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
143143
BasicBlock* back_blk_ptr = &*new_blocks->back();
144144
InstructionBuilder builder(
@@ -168,14 +168,14 @@ void InstDebugPrintfPass::GenOutputCode(
168168
});
169169
GenDebugStreamWrite(
170170
builder.GetUintConstantId(shader_id_),
171-
builder.GetUintConstantId(uid2offset_[printf_inst->unique_id()]),
172-
GenStageInfo(stage_idx, &builder), val_ids, &builder);
171+
builder.GetUintConstantId(uid2offset_[printf_inst->unique_id()]), val_ids,
172+
&builder);
173173
context()->KillInst(printf_inst);
174174
}
175175

176176
void InstDebugPrintfPass::GenDebugPrintfCode(
177177
BasicBlock::iterator ref_inst_itr,
178-
UptrVectorIterator<BasicBlock> ref_block_itr, uint32_t stage_idx,
178+
UptrVectorIterator<BasicBlock> ref_block_itr,
179179
std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
180180
// If not DebugPrintf OpExtInst, return.
181181
Instruction* printf_inst = &*ref_inst_itr;
@@ -191,7 +191,7 @@ void InstDebugPrintfPass::GenDebugPrintfCode(
191191
MovePreludeCode(ref_inst_itr, ref_block_itr, &new_blk_ptr);
192192
new_blocks->push_back(std::move(new_blk_ptr));
193193
// Generate instructions to output printf args to printf buffer
194-
GenOutputCode(printf_inst, stage_idx, new_blocks);
194+
GenOutputCode(printf_inst, new_blocks);
195195
// Caller expects at least two blocks with last block containing remaining
196196
// code, so end block after instrumentation, create remainder block, and
197197
// branch to it
@@ -301,8 +301,7 @@ uint32_t InstDebugPrintfPass::GetStreamWriteFunctionId(uint32_t param_cnt) {
301301
enum {
302302
kShaderId = 0,
303303
kInstructionIndex = 1,
304-
kStageInfo = 2,
305-
kFirstParam = 3,
304+
kFirstParam = 2,
306305
};
307306
// Total param count is common params plus validation-specific
308307
// params
@@ -312,12 +311,9 @@ uint32_t InstDebugPrintfPass::GetStreamWriteFunctionId(uint32_t param_cnt) {
312311
analysis::TypeManager* type_mgr = context()->get_type_mgr();
313312

314313
const analysis::Type* uint_type = GetInteger(32, false);
315-
const analysis::Vector v4uint(uint_type, 4);
316-
const analysis::Type* v4uint_type = type_mgr->GetRegisteredType(&v4uint);
317314

318315
std::vector<const analysis::Type*> param_types(kFirstParam + param_cnt,
319316
uint_type);
320-
param_types[kStageInfo] = v4uint_type;
321317
std::unique_ptr<Function> output_func = StartFunction(
322318
param2output_func_id_[param_cnt], type_mgr->GetVoidType(), param_types);
323319

@@ -330,8 +326,8 @@ uint32_t InstDebugPrintfPass::GetStreamWriteFunctionId(uint32_t param_cnt) {
330326
context(), &*new_blk_ptr,
331327
IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
332328
// Gen test if debug output buffer size will not be exceeded.
333-
const uint32_t val_spec_offset = kInstStageOutCnt;
334-
const uint32_t obuf_record_sz = val_spec_offset + param_cnt;
329+
const uint32_t first_param_offset = kInstCommonOutInstructionIdx + 1;
330+
const uint32_t obuf_record_sz = first_param_offset + param_cnt;
335331
const uint32_t buf_id = GetOutputBufferId();
336332
const uint32_t buf_uint_ptr_id = GetOutputBufferPtrId();
337333
Instruction* obuf_curr_sz_ac_inst = builder.AddAccessChain(
@@ -382,16 +378,9 @@ uint32_t InstDebugPrintfPass::GetStreamWriteFunctionId(uint32_t param_cnt) {
382378
// Store Instruction Idx
383379
GenDebugOutputFieldCode(obuf_curr_sz_id, kInstCommonOutInstructionIdx,
384380
param_ids[kInstructionIndex], &builder);
385-
// Store stage info. Stage Idx + 3 words of stage-specific data.
386-
for (uint32_t i = 0; i < 4; ++i) {
387-
Instruction* field =
388-
builder.AddCompositeExtract(GetUintId(), param_ids[kStageInfo], {i});
389-
GenDebugOutputFieldCode(obuf_curr_sz_id, kInstCommonOutStageIdx + i,
390-
field->result_id(), &builder);
391-
}
392381
// Gen writes of validation specific data
393382
for (uint32_t i = 0; i < param_cnt; ++i) {
394-
GenDebugOutputFieldCode(obuf_curr_sz_id, val_spec_offset + i,
383+
GenDebugOutputFieldCode(obuf_curr_sz_id, first_param_offset + i,
395384
param_ids[kFirstParam + i], &builder);
396385
}
397386
// Close write block and gen merge block
@@ -416,12 +405,12 @@ uint32_t InstDebugPrintfPass::GetStreamWriteFunctionId(uint32_t param_cnt) {
416405
}
417406

418407
void InstDebugPrintfPass::GenDebugStreamWrite(
419-
uint32_t shader_id, uint32_t instruction_idx_id, uint32_t stage_info_id,
408+
uint32_t shader_id, uint32_t instruction_idx_id,
420409
const std::vector<uint32_t>& validation_ids, InstructionBuilder* builder) {
421410
// Call debug output function. Pass func_idx, instruction_idx and
422411
// validation ids as args.
423412
uint32_t val_id_cnt = static_cast<uint32_t>(validation_ids.size());
424-
std::vector<uint32_t> args = {shader_id, instruction_idx_id, stage_info_id};
413+
std::vector<uint32_t> args = {shader_id, instruction_idx_id};
425414
(void)args.insert(args.end(), validation_ids.begin(), validation_ids.end());
426415
(void)builder->AddFunctionCall(GetVoidId(),
427416
GetStreamWriteFunctionId(val_id_cnt), args);
@@ -455,10 +444,10 @@ Pass::Status InstDebugPrintfPass::ProcessImpl() {
455444
// Perform printf instrumentation on each entry point function in module
456445
InstProcessFunction pfn =
457446
[this](BasicBlock::iterator ref_inst_itr,
458-
UptrVectorIterator<BasicBlock> ref_block_itr, uint32_t stage_idx,
447+
UptrVectorIterator<BasicBlock> ref_block_itr,
448+
[[maybe_unused]] uint32_t stage_idx,
459449
std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
460-
return GenDebugPrintfCode(ref_inst_itr, ref_block_itr, stage_idx,
461-
new_blocks);
450+
return GenDebugPrintfCode(ref_inst_itr, ref_block_itr, new_blocks);
462451
};
463452
(void)InstProcessEntryPointCallTree(pfn);
464453
// Remove DebugPrintf OpExtInstImport instruction

source/opt/inst_debug_printf_pass.h

+7-26
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ namespace opt {
2828
class InstDebugPrintfPass : public InstrumentPass {
2929
public:
3030
// For test harness only
31-
InstDebugPrintfPass() : InstrumentPass(7, 23) {}
31+
InstDebugPrintfPass() : InstrumentPass(7, 23, false, false) {}
3232
// For all other interfaces
3333
InstDebugPrintfPass(uint32_t desc_set, uint32_t shader_id)
34-
: InstrumentPass(desc_set, shader_id) {}
34+
: InstrumentPass(desc_set, shader_id, false, false) {}
3535

3636
~InstDebugPrintfPass() override = default;
3737

@@ -52,9 +52,7 @@ class InstDebugPrintfPass : public InstrumentPass {
5252
// validation and write a record to the end of the stream, if enough space
5353
// in the buffer remains. The record will contain the index of the function
5454
// and instruction within that function |func_idx, instruction_idx| which
55-
// generated the record. It will also contain additional information to
56-
// identify the instance of the shader, depending on the stage |stage_idx|
57-
// of the shader. Finally, the record will contain validation-specific
55+
// generated the record. Finally, the record will contain validation-specific
5856
// data contained in |validation_ids| which will identify the validation
5957
// error as well as the values involved in the error.
6058
//
@@ -83,18 +81,15 @@ class InstDebugPrintfPass : public InstrumentPass {
8381
// Record Size
8482
// Shader ID
8583
// Instruction Index
86-
// Stage
87-
// Stage-specific Word 0
88-
// Stage-specific Word 1
8984
// ...
9085
// Validation Error Code
9186
// Validation-specific Word 0
9287
// Validation-specific Word 1
9388
// Validation-specific Word 2
9489
// ...
9590
//
96-
// Each record consists of three subsections: members common across all
97-
// validation, members specific to the stage, and members specific to a
91+
// Each record consists of two subsections: members common across all
92+
// validation and members specific to a
9893
// validation.
9994
//
10095
// The Record Size is the number of 32-bit words in the record, including
@@ -106,18 +101,6 @@ class InstDebugPrintfPass : public InstrumentPass {
106101
// The Instruction Index is the position of the instruction within the
107102
// SPIR-V file which is in error.
108103
//
109-
// The Stage is the pipeline stage which has generated the error as defined
110-
// by the SpvExecutionModel_ enumeration. This is used to interpret the
111-
// following Stage-specific words.
112-
//
113-
// The Stage-specific Words identify which invocation of the shader generated
114-
// the error. Every stage will write a fixed number of words. Vertex shaders
115-
// will write the Vertex and Instance ID. Fragment shaders will write
116-
// FragCoord.xy. Compute shaders will write the GlobalInvocation ID.
117-
// The tessellation eval shader will write the Primitive ID and TessCoords.uv.
118-
// The tessellation control shader and geometry shader will write the
119-
// Primitive ID and Invocation ID.
120-
//
121104
// The Validation Error Code specifies the exact error which has occurred.
122105
// These are enumerated with the kInstError* static consts. This allows
123106
// multiple validation layers to use the same, single output buffer.
@@ -131,7 +114,6 @@ class InstDebugPrintfPass : public InstrumentPass {
131114
// before writing, the size of the debug out buffer can be used by the
132115
// validation layer to control the number of error records that are written.
133116
void GenDebugStreamWrite(uint32_t shader_id, uint32_t instruction_idx_id,
134-
uint32_t stage_info_id,
135117
const std::vector<uint32_t>& validation_ids,
136118
InstructionBuilder* builder);
137119

@@ -144,7 +126,7 @@ class InstDebugPrintfPass : public InstrumentPass {
144126
// If |ref_inst_itr| is an OpDebugPrintf, return in |new_blocks| the result
145127
// of replacing it with buffer write instructions within its block at
146128
// |ref_block_itr|. The instructions write a record to the printf
147-
// output buffer stream including |function_idx, instruction_idx, stage_idx|
129+
// output buffer stream including |function_idx, instruction_idx|
148130
// and removes the OpDebugPrintf. The block at |ref_block_itr| can just be
149131
// replaced with the block in |new_blocks|. Besides the buffer writes, this
150132
// block will comprise all instructions preceding and following
@@ -162,7 +144,6 @@ class InstDebugPrintfPass : public InstrumentPass {
162144
// DebugPrintf.
163145
void GenDebugPrintfCode(BasicBlock::iterator ref_inst_itr,
164146
UptrVectorIterator<BasicBlock> ref_block_itr,
165-
uint32_t stage_idx,
166147
std::vector<std::unique_ptr<BasicBlock>>* new_blocks);
167148

168149
// Generate a sequence of uint32 instructions in |builder| (if necessary)
@@ -175,7 +156,7 @@ class InstDebugPrintfPass : public InstrumentPass {
175156
// Generate instructions to write a record containing the operands of
176157
// |printf_inst| arguments to printf buffer, adding new code to the end of
177158
// the last block in |new_blocks|. Kill OpDebugPrintf instruction.
178-
void GenOutputCode(Instruction* printf_inst, uint32_t stage_idx,
159+
void GenOutputCode(Instruction* printf_inst,
179160
std::vector<std::unique_ptr<BasicBlock>>* new_blocks);
180161

181162
// Set the name for a function or global variable, names will be

0 commit comments

Comments
 (0)