Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

printf: Remove stage specific info #5495

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 0 additions & 70 deletions include/spirv-tools/instrument.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion source/opt/inst_bindless_check_pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
5 changes: 3 additions & 2 deletions source/opt/inst_buff_addr_check_pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
39 changes: 14 additions & 25 deletions source/opt/inst_debug_printf_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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);

Expand All @@ -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(
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Down
33 changes: 7 additions & 26 deletions source/opt/inst_debug_printf_pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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.
//
Expand Down Expand Up @@ -83,18 +81,15 @@ 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
// Validation-specific Word 1
// 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
Expand All @@ -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.
Expand All @@ -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);

Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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
Expand Down
Loading