instrument: Reduce number of inst_bindless_stream_write_6 calls (#5327)

Multiple calls to this function were causing vkCreateGraphicsPipelines
to be 3x slower on some driver. I suspect this was because each
call had to be inlined separately which bloated the code and caused
more work in the driver's SPIRV -> native instruction compilation.
This commit is contained in:
Jeremy Gebben 2023-08-01 13:49:12 -06:00 committed by GitHub
parent 02cd71d41c
commit 47fff21d52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 491 additions and 226 deletions

View File

@ -132,50 +132,58 @@ void InstBindlessCheckPass::SetupInputBufferIds() {
// clang-format off // clang-format off
// GLSL: // GLSL:
//bool inst_bindless_check_desc(uint shader_id, uint line, uvec4 stage_info, uint desc_set_idx, uint binding_idx, uint desc_idx, //bool inst_bindless_check_desc(uint shader_id, uint inst_num, uvec4 stage_info, uint desc_set, uint binding, uint desc_index,
// uint offset) // uint byte_offset)
//{ //{
// if (desc_set_idx >= inst_bindless_input_buffer.desc_sets.length()) { // uint error = 0u;
// // kInstErrorBindlessBounds // uint param5 = 0u;
// inst_bindless_stream_write_6(shader_id, line, stage_info, 1, desc_set_idx, binding_idx, desc_idx, 0, 0); // uint param6 = 0u;
// return false; // uint num_bindings = 0u;
// uint init_state = 0u;
// if (desc_set >= 32u) {
// error = 1u;
// } // }
// DescriptorSetData set_data = inst_bindless_input_buffer.desc_sets[desc_set_idx]; // inst_bindless_DescriptorSetData set_data;
// uvec2 ptr_vec = uvec2(set_data); // if (error == 0u) {
// if (ptr_vec.x == 0 && ptr_vec.y == 0) { // set_data = inst_bindless_input_buffer.desc_sets[desc_set];
// // kInstErrorBindlessBounds // uvec2 ptr_vec = uvec2(set_data);
// inst_bindless_stream_write_6(shader_id, line, stage_info, 1, desc_set_idx, binding_idx, desc_idx, 0, 0); // if ((ptr_vec.x == 0u) && (ptr_vec.y == 0u)) {
// return false; // error = 1u;
// }
// } // }
// uint num_bindings = set_data.num_bindings; // if (error == 0u) {
// if (binding_idx >= num_bindings) { // num_bindings = set_data.num_bindings;
// // kInstErrorBindlessBounds // if (binding >= num_bindings) {
// inst_bindless_stream_write_6(shader_id, line, stage_info, 1, desc_set_idx, binding_idx, desc_idx, 0, 0); // error = 1u;
// return false; // }
// } // }
// uint binding_length = set_data.data[binding_idx]; // if (error == 0u) {
// if (desc_idx >= binding_length) { // if (desc_index >= set_data.data[binding]) {
// // kInstErrorBindlessBounds // error = 1u;
// inst_bindless_stream_write_6(shader_id, line, stage_info, 1, desc_set_idx, binding_idx, desc_idx, binding_length, 0); // param5 = set_data.data[binding];
// return false; // }
// } // }
// uint desc_records_start = set_data.data[num_bindings + binding_idx]; // if (0u == error) {
// uint init_or_len = set_data.data[desc_records_start + desc_idx]; // uint state_index = set_data.data[num_bindings + binding] + desc_index;
// if (init_or_len == 0) { // init_state = set_data.data[state_index];
// // kInstErrorBindlessUninit // if (init_state == 0u) {
// inst_bindless_stream_write_6(shader_id, line, stage_info, 2, desc_set_idx, binding_idx, desc_idx, 0, 0); // error = 2u;
// return false; // }
// } // }
// if (offset >= init_or_len) { // if (error == 0u) {
// // kInstErrorOOB // if (byte_offset >= init_state) {
// inst_bindless_stream_write_6(shader_id, line, stage_info, 4, desc_set_idx, binding_idx, desc_idx, offset, // error = 4u;
// init_or_len); // param5 = byte_offset;
// param6 = init_state;
// }
// }
// if (0u != error) {
// inst_bindless_stream_write_6(shader_id, inst_num, stage_info, error, desc_set, binding, desc_index, param5, param6);
// return false; // return false;
// } // }
// return true; // return true;
//} //}
// clang-format on // clang-format on
uint32_t InstBindlessCheckPass::GenDescCheckFunctionId() { uint32_t InstBindlessCheckPass::GenDescCheckFunctionId() {
enum { enum {
kShaderId = 0, kShaderId = 0,
@ -205,235 +213,427 @@ uint32_t InstBindlessCheckPass::GenDescCheckFunctionId() {
const std::vector<uint32_t> param_ids = AddParameters(*func, param_types); const std::vector<uint32_t> param_ids = AddParameters(*func, param_types);
const uint32_t func_uint_ptr =
type_mgr->FindPointerToType(GetUintId(), spv::StorageClass::Function);
// Create block // Create block
auto new_blk_ptr = MakeUnique<BasicBlock>(NewLabel(TakeNextId())); auto new_blk_ptr = MakeUnique<BasicBlock>(NewLabel(TakeNextId()));
InstructionBuilder builder( InstructionBuilder builder(
context(), new_blk_ptr.get(), context(), new_blk_ptr.get(),
IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
Instruction* inst;
const uint32_t zero_id = builder.GetUintConstantId(0);
const uint32_t false_id = builder.GetBoolConstantId(false); const uint32_t false_id = builder.GetBoolConstantId(false);
const uint32_t true_id = builder.GetBoolConstantId(true); const uint32_t true_id = builder.GetBoolConstantId(true);
Instruction* inst; const uint32_t uint_ptr = type_mgr->FindPointerToType(
GetUintId(), spv::StorageClass::PhysicalStorageBuffer);
inst = builder.AddBinaryOp(func_uint_ptr, spv::Op::OpVariable,
uint32_t(spv::StorageClass::Function), zero_id);
const uint32_t error_var = inst->result_id();
inst = builder.AddBinaryOp(func_uint_ptr, spv::Op::OpVariable,
uint32_t(spv::StorageClass::Function), zero_id);
const uint32_t param5_var = inst->result_id();
inst = builder.AddBinaryOp(func_uint_ptr, spv::Op::OpVariable,
uint32_t(spv::StorageClass::Function), zero_id);
const uint32_t param6_var = inst->result_id();
inst = builder.AddBinaryOp(func_uint_ptr, spv::Op::OpVariable,
uint32_t(spv::StorageClass::Function), zero_id);
const uint32_t num_bindings_var = inst->result_id();
inst = builder.AddBinaryOp(func_uint_ptr, spv::Op::OpVariable,
uint32_t(spv::StorageClass::Function), zero_id);
const uint32_t init_status_var = inst->result_id();
const uint32_t desc_set_ptr_ptr = type_mgr->FindPointerToType(
desc_set_ptr_id_, spv::StorageClass::Function);
inst = builder.AddUnaryOp(desc_set_ptr_ptr, spv::Op::OpVariable,
uint32_t(spv::StorageClass::Function));
const uint32_t desc_set_ptr_var = inst->result_id();
get_decoration_mgr()->AddDecoration(
desc_set_ptr_var, uint32_t(spv::Decoration::AliasedPointer));
uint32_t check_label_id = TakeNextId();
auto check_label = NewLabel(check_label_id);
uint32_t skip_label_id = TakeNextId();
auto skip_label = NewLabel(skip_label_id);
inst = builder.AddBinaryOp( inst = builder.AddBinaryOp(
GetBoolId(), spv::Op::OpUGreaterThanEqual, param_ids[kDescSet], GetBoolId(), spv::Op::OpUGreaterThanEqual, param_ids[kDescSet],
builder.GetUintConstantId(kDebugInputBindlessMaxDescSets)); builder.GetUintConstantId(kDebugInputBindlessMaxDescSets));
const uint32_t desc_cmp_id = inst->result_id(); const uint32_t desc_cmp_id = inst->result_id();
uint32_t error_blk_id = TakeNextId(); (void)builder.AddConditionalBranch(desc_cmp_id, check_label_id, skip_label_id,
uint32_t merge_blk_id = TakeNextId(); skip_label_id);
std::unique_ptr<Instruction> merge_label(NewLabel(merge_blk_id));
std::unique_ptr<Instruction> error_label(NewLabel(error_blk_id));
(void)builder.AddConditionalBranch(desc_cmp_id, error_blk_id, merge_blk_id,
merge_blk_id);
func->AddBasicBlock(std::move(new_blk_ptr)); func->AddBasicBlock(std::move(new_blk_ptr));
// error return // set error
new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label)); new_blk_ptr = MakeUnique<BasicBlock>(std::move(check_label));
builder.SetInsertPoint(&*new_blk_ptr); builder.SetInsertPoint(&*new_blk_ptr);
(void)builder.AddUnaryOp(0, spv::Op::OpReturnValue, false_id); builder.AddStore(error_var,
builder.GetUintConstantId(kInstErrorBindlessBounds));
builder.AddBranch(skip_label_id);
func->AddBasicBlock(std::move(new_blk_ptr)); func->AddBasicBlock(std::move(new_blk_ptr));
// check descriptor set table entry is non-null // check descriptor set table entry is non-null
new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label)); new_blk_ptr = MakeUnique<BasicBlock>(std::move(skip_label));
builder.SetInsertPoint(&*new_blk_ptr); builder.SetInsertPoint(&*new_blk_ptr);
const uint32_t desc_set_ptr_ptr = type_mgr->FindPointerToType( check_label_id = TakeNextId();
desc_set_ptr_id_, spv::StorageClass::StorageBuffer); check_label = NewLabel(check_label_id);
skip_label_id = TakeNextId();
skip_label = NewLabel(skip_label_id);
inst = builder.AddLoad(GetUintId(), error_var);
uint32_t error_val_id = inst->result_id();
inst = builder.AddAccessChain( inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, error_val_id,
desc_set_ptr_ptr, input_buffer_id_, zero_id);
{builder.GetUintConstantId(0), param_ids[kDescSet]}); uint32_t no_error_id = inst->result_id();
const uint32_t set_access_chain_id = inst->result_id(); (void)builder.AddConditionalBranch(no_error_id, check_label_id, skip_label_id,
skip_label_id);
inst = builder.AddLoad(desc_set_ptr_id_, set_access_chain_id);
const uint32_t desc_set_ptr_id = inst->result_id();
inst =
builder.AddUnaryOp(GetVecUintId(2), spv::Op::OpBitcast, desc_set_ptr_id);
const uint32_t ptr_as_uvec_id = inst->result_id();
inst = builder.AddCompositeExtract(GetUintId(), ptr_as_uvec_id, {0});
const uint32_t uvec_x = inst->result_id();
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, uvec_x,
builder.GetUintConstantId(0));
const uint32_t x_is_zero_id = inst->result_id();
inst = builder.AddCompositeExtract(GetUintId(), ptr_as_uvec_id, {1});
const uint32_t uvec_y = inst->result_id();
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, uvec_y,
builder.GetUintConstantId(0));
const uint32_t y_is_zero_id = inst->result_id();
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpLogicalAnd, x_is_zero_id,
y_is_zero_id);
const uint32_t is_null_id = inst->result_id();
error_blk_id = TakeNextId();
merge_blk_id = TakeNextId();
merge_label = NewLabel(merge_blk_id);
error_label = NewLabel(error_blk_id);
(void)builder.AddConditionalBranch(is_null_id, error_blk_id, merge_blk_id,
merge_blk_id);
func->AddBasicBlock(std::move(new_blk_ptr)); func->AddBasicBlock(std::move(new_blk_ptr));
// error return
new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label)); new_blk_ptr = MakeUnique<BasicBlock>(std::move(check_label));
builder.SetInsertPoint(&*new_blk_ptr); builder.SetInsertPoint(&*new_blk_ptr);
GenDebugStreamWrite(
param_ids[kShaderId], param_ids[kInstructionIndex], param_ids[kStageInfo], {
{builder.GetUintConstantId(kInstErrorBindlessBounds), param_ids[kDescSet], const uint32_t desc_set_ptr_ptr_sb = type_mgr->FindPointerToType(
param_ids[kDescBinding], param_ids[kDescIndex], desc_set_ptr_id_, spv::StorageClass::StorageBuffer);
builder.GetUintConstantId(0), builder.GetUintConstantId(0)},
&builder); inst = builder.AddAccessChain(desc_set_ptr_ptr_sb, input_buffer_id_,
(void)builder.AddUnaryOp(0, spv::Op::OpReturnValue, false_id); {zero_id, param_ids[kDescSet]});
const uint32_t set_access_chain_id = inst->result_id();
inst = builder.AddLoad(desc_set_ptr_id_, set_access_chain_id);
const uint32_t desc_set_ptr_id = inst->result_id();
builder.AddStore(desc_set_ptr_var, desc_set_ptr_id);
inst = builder.AddUnaryOp(GetVecUintId(2), spv::Op::OpBitcast,
desc_set_ptr_id);
const uint32_t ptr_as_uvec_id = inst->result_id();
inst = builder.AddCompositeExtract(GetUintId(), ptr_as_uvec_id, {0});
const uint32_t uvec_x = inst->result_id();
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, uvec_x, zero_id);
const uint32_t x_is_zero_id = inst->result_id();
inst = builder.AddCompositeExtract(GetUintId(), ptr_as_uvec_id, {1});
const uint32_t uvec_y = inst->result_id();
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, uvec_y, zero_id);
const uint32_t y_is_zero_id = inst->result_id();
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpLogicalAnd, x_is_zero_id,
y_is_zero_id);
const uint32_t is_null_id = inst->result_id();
const uint32_t error_label_id = TakeNextId();
auto error_label = NewLabel(error_label_id);
const uint32_t merge_label_id = TakeNextId();
auto merge_label = NewLabel(merge_label_id);
(void)builder.AddConditionalBranch(is_null_id, error_label_id,
merge_label_id, merge_label_id);
func->AddBasicBlock(std::move(new_blk_ptr));
// set error
new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label));
builder.SetInsertPoint(&*new_blk_ptr);
builder.AddStore(error_var,
builder.GetUintConstantId(kInstErrorBindlessBounds));
builder.AddBranch(merge_label_id);
func->AddBasicBlock(std::move(new_blk_ptr));
new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
builder.SetInsertPoint(&*new_blk_ptr);
builder.AddBranch(skip_label_id);
func->AddBasicBlock(std::move(new_blk_ptr));
}
new_blk_ptr = MakeUnique<BasicBlock>(std::move(skip_label));
builder.SetInsertPoint(&*new_blk_ptr);
check_label_id = TakeNextId();
check_label = NewLabel(check_label_id);
skip_label_id = TakeNextId();
skip_label = NewLabel(skip_label_id);
inst = builder.AddLoad(GetUintId(), error_var);
error_val_id = inst->result_id();
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, error_val_id,
zero_id);
no_error_id = inst->result_id();
(void)builder.AddConditionalBranch(no_error_id, check_label_id, skip_label_id,
skip_label_id);
func->AddBasicBlock(std::move(new_blk_ptr)); func->AddBasicBlock(std::move(new_blk_ptr));
// check binding is in range // check binding is in range
new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label)); new_blk_ptr = MakeUnique<BasicBlock>(std::move(check_label));
builder.SetInsertPoint(&*new_blk_ptr); builder.SetInsertPoint(&*new_blk_ptr);
{
inst = builder.AddLoad(desc_set_ptr_id_, desc_set_ptr_var);
const uint32_t desc_set_ptr_id = inst->result_id();
const uint32_t uint_ptr = type_mgr->FindPointerToType( inst = builder.AddAccessChain(uint_ptr, desc_set_ptr_id, {zero_id});
GetUintId(), spv::StorageClass::PhysicalStorageBuffer); const uint32_t binding_access_chain_id = inst->result_id();
inst = builder.AddAccessChain(uint_ptr, desc_set_ptr_id, inst = builder.AddLoad(GetUintId(), binding_access_chain_id, 8);
{builder.GetUintConstantId(0)}); const uint32_t num_bindings_id = inst->result_id();
const uint32_t binding_access_chain_id = inst->result_id();
inst = builder.AddLoad(GetUintId(), binding_access_chain_id, 8); builder.AddStore(num_bindings_var, num_bindings_id);
const uint32_t num_bindings_id = inst->result_id();
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpUGreaterThanEqual, inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpUGreaterThanEqual,
param_ids[kDescBinding], num_bindings_id); param_ids[kDescBinding], num_bindings_id);
const uint32_t bindings_cmp_id = inst->result_id(); const uint32_t bindings_cmp_id = inst->result_id();
error_blk_id = TakeNextId(); const uint32_t error_label_id = TakeNextId();
merge_blk_id = TakeNextId(); auto error_label = NewLabel(error_label_id);
merge_label = NewLabel(merge_blk_id); const uint32_t merge_label_id = TakeNextId();
error_label = NewLabel(error_blk_id); auto merge_label = NewLabel(merge_label_id);
(void)builder.AddConditionalBranch(bindings_cmp_id, error_blk_id, (void)builder.AddConditionalBranch(bindings_cmp_id, error_label_id,
merge_blk_id, merge_blk_id); merge_label_id, merge_label_id);
func->AddBasicBlock(std::move(new_blk_ptr)); func->AddBasicBlock(std::move(new_blk_ptr));
// error return // set error
new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label)); new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label));
builder.SetInsertPoint(&*new_blk_ptr); builder.SetInsertPoint(&*new_blk_ptr);
GenDebugStreamWrite( builder.AddStore(error_var,
param_ids[kShaderId], param_ids[kInstructionIndex], param_ids[kStageInfo], builder.GetUintConstantId(kInstErrorBindlessBounds));
{builder.GetUintConstantId(kInstErrorBindlessBounds), param_ids[kDescSet], builder.AddBranch(merge_label_id);
param_ids[kDescBinding], param_ids[kDescIndex], func->AddBasicBlock(std::move(new_blk_ptr));
builder.GetUintConstantId(0), builder.GetUintConstantId(0)},
&builder); new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
(void)builder.AddUnaryOp(0, spv::Op::OpReturnValue, false_id); builder.SetInsertPoint(&*new_blk_ptr);
func->AddBasicBlock(std::move(new_blk_ptr)); builder.AddBranch(skip_label_id);
func->AddBasicBlock(std::move(new_blk_ptr));
}
// read binding length // read binding length
new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label)); new_blk_ptr = MakeUnique<BasicBlock>(std::move(skip_label));
builder.SetInsertPoint(&*new_blk_ptr); builder.SetInsertPoint(&*new_blk_ptr);
inst = builder.AddAccessChain( check_label_id = TakeNextId();
uint_ptr, desc_set_ptr_id, check_label = NewLabel(check_label_id);
{{builder.GetUintConstantId(1), param_ids[kDescBinding]}}); skip_label_id = TakeNextId();
const uint32_t length_ac_id = inst->result_id(); skip_label = NewLabel(skip_label_id);
inst = builder.AddLoad(GetUintId(), length_ac_id, sizeof(uint32_t)); inst = builder.AddLoad(GetUintId(), error_var);
const uint32_t length_id = inst->result_id(); error_val_id = inst->result_id();
// Check descriptor index in bounds inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, error_val_id,
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpUGreaterThanEqual, zero_id);
param_ids[kDescIndex], length_id); no_error_id = inst->result_id();
const uint32_t desc_idx_range_id = inst->result_id(); (void)builder.AddConditionalBranch(no_error_id, check_label_id, skip_label_id,
skip_label_id);
error_blk_id = TakeNextId();
merge_blk_id = TakeNextId();
merge_label = NewLabel(merge_blk_id);
error_label = NewLabel(error_blk_id);
(void)builder.AddConditionalBranch(desc_idx_range_id, error_blk_id,
merge_blk_id, merge_blk_id);
func->AddBasicBlock(std::move(new_blk_ptr)); func->AddBasicBlock(std::move(new_blk_ptr));
// Error return
new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label)); new_blk_ptr = MakeUnique<BasicBlock>(std::move(check_label));
builder.SetInsertPoint(&*new_blk_ptr); builder.SetInsertPoint(&*new_blk_ptr);
GenDebugStreamWrite( {
param_ids[kShaderId], param_ids[kInstructionIndex], param_ids[kStageInfo], inst = builder.AddLoad(desc_set_ptr_id_, desc_set_ptr_var);
{builder.GetUintConstantId(kInstErrorBindlessBounds), param_ids[kDescSet], const uint32_t desc_set_ptr_id = inst->result_id();
param_ids[kDescBinding], param_ids[kDescIndex], length_id,
builder.GetUintConstantId(0)}, inst = builder.AddAccessChain(
&builder); uint_ptr, desc_set_ptr_id,
(void)builder.AddUnaryOp(0, spv::Op::OpReturnValue, false_id); {{builder.GetUintConstantId(1), param_ids[kDescBinding]}});
const uint32_t length_ac_id = inst->result_id();
inst = builder.AddLoad(GetUintId(), length_ac_id, sizeof(uint32_t));
const uint32_t length_id = inst->result_id();
// Check descriptor index in bounds
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpUGreaterThanEqual,
param_ids[kDescIndex], length_id);
const uint32_t desc_idx_range_id = inst->result_id();
const uint32_t error_label_id = TakeNextId();
auto error_label = NewLabel(error_label_id);
const uint32_t merge_label_id = TakeNextId();
auto merge_label = NewLabel(merge_label_id);
(void)builder.AddConditionalBranch(desc_idx_range_id, error_label_id,
merge_label_id, merge_label_id);
func->AddBasicBlock(std::move(new_blk_ptr));
// set error
new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label));
builder.SetInsertPoint(&*new_blk_ptr);
builder.AddStore(error_var,
builder.GetUintConstantId(kInstErrorBindlessBounds));
builder.AddStore(param5_var, length_id);
builder.AddBranch(merge_label_id);
func->AddBasicBlock(std::move(new_blk_ptr));
new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
builder.SetInsertPoint(&*new_blk_ptr);
builder.AddBranch(skip_label_id);
func->AddBasicBlock(std::move(new_blk_ptr));
}
new_blk_ptr = MakeUnique<BasicBlock>(std::move(skip_label));
builder.SetInsertPoint(&*new_blk_ptr);
inst = builder.AddLoad(GetUintId(), error_var);
error_val_id = inst->result_id();
check_label_id = TakeNextId();
check_label = NewLabel(check_label_id);
skip_label_id = TakeNextId();
skip_label = NewLabel(skip_label_id);
inst = builder.AddLoad(GetUintId(), error_var);
error_val_id = inst->result_id();
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, zero_id,
error_val_id);
no_error_id = inst->result_id();
(void)builder.AddConditionalBranch(no_error_id, check_label_id, skip_label_id,
skip_label_id);
func->AddBasicBlock(std::move(new_blk_ptr)); func->AddBasicBlock(std::move(new_blk_ptr));
// Read descriptor init status // Read descriptor init status
new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label)); new_blk_ptr = MakeUnique<BasicBlock>(std::move(check_label));
builder.SetInsertPoint(&*new_blk_ptr); builder.SetInsertPoint(&*new_blk_ptr);
{
inst = builder.AddLoad(desc_set_ptr_id_, desc_set_ptr_var);
const uint32_t desc_set_ptr_id = inst->result_id();
inst = builder.AddIAdd(GetUintId(), num_bindings_id, param_ids[kDescBinding]); inst = builder.AddLoad(GetUintId(), num_bindings_var);
const uint32_t state_offset_id = inst->result_id(); const uint32_t num_bindings_id = inst->result_id();
inst = inst =
builder.AddAccessChain(uint_ptr, desc_set_ptr_id, builder.AddIAdd(GetUintId(), num_bindings_id, param_ids[kDescBinding]);
{{builder.GetUintConstantId(1), state_offset_id}}); const uint32_t state_offset_id = inst->result_id();
const uint32_t state_start_ac_id = inst->result_id();
inst = builder.AddLoad(GetUintId(), state_start_ac_id, sizeof(uint32_t)); inst = builder.AddAccessChain(
const uint32_t state_start_id = inst->result_id(); uint_ptr, desc_set_ptr_id,
{{builder.GetUintConstantId(1), state_offset_id}});
const uint32_t state_start_ac_id = inst->result_id();
inst = builder.AddIAdd(GetUintId(), state_start_id, param_ids[kDescIndex]); inst = builder.AddLoad(GetUintId(), state_start_ac_id, sizeof(uint32_t));
const uint32_t state_entry_id = inst->result_id(); const uint32_t state_start_id = inst->result_id();
// Note: length starts from the beginning of the buffer, not the beginning of inst = builder.AddIAdd(GetUintId(), state_start_id, param_ids[kDescIndex]);
// the data array const uint32_t state_entry_id = inst->result_id();
inst =
builder.AddAccessChain(uint_ptr, desc_set_ptr_id,
{{builder.GetUintConstantId(1), state_entry_id}});
const uint32_t init_ac_id = inst->result_id();
inst = builder.AddLoad(GetUintId(), init_ac_id, sizeof(uint32_t)); // Note: length starts from the beginning of the buffer, not the beginning
const uint32_t init_status_id = inst->result_id(); // of the data array
inst = builder.AddAccessChain(
uint_ptr, desc_set_ptr_id,
{{builder.GetUintConstantId(1), state_entry_id}});
const uint32_t init_ac_id = inst->result_id();
// Check for uninitialized descriptor inst = builder.AddLoad(GetUintId(), init_ac_id, sizeof(uint32_t));
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, init_status_id, const uint32_t init_status_id = inst->result_id();
builder.GetUintConstantId(0));
const uint32_t uninit_check_id = inst->result_id(); builder.AddStore(init_status_var, init_status_id);
error_blk_id = TakeNextId();
merge_blk_id = TakeNextId(); // Check for uninitialized descriptor
merge_label = NewLabel(merge_blk_id); inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, init_status_id,
error_label = NewLabel(error_blk_id); zero_id);
(void)builder.AddConditionalBranch(uninit_check_id, error_blk_id, const uint32_t uninit_check_id = inst->result_id();
merge_blk_id, merge_blk_id); const uint32_t error_label_id = TakeNextId();
func->AddBasicBlock(std::move(new_blk_ptr)); auto error_label = NewLabel(error_label_id);
new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label)); const uint32_t merge_label_id = TakeNextId();
builder.SetInsertPoint(&*new_blk_ptr); auto merge_label = NewLabel(merge_label_id);
GenDebugStreamWrite( (void)builder.AddConditionalBranch(uninit_check_id, error_label_id,
param_ids[kShaderId], param_ids[kInstructionIndex], param_ids[kStageInfo], merge_label_id, merge_label_id);
{builder.GetUintConstantId(kInstErrorBindlessUninit), param_ids[kDescSet], func->AddBasicBlock(std::move(new_blk_ptr));
param_ids[kDescBinding], param_ids[kDescIndex], new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label));
builder.GetUintConstantId(0), builder.GetUintConstantId(0)}, builder.SetInsertPoint(&*new_blk_ptr);
&builder); builder.AddStore(error_var,
(void)builder.AddUnaryOp(0, spv::Op::OpReturnValue, false_id); builder.GetUintConstantId(kInstErrorBindlessUninit));
func->AddBasicBlock(std::move(new_blk_ptr)); builder.AddBranch(merge_label_id);
func->AddBasicBlock(std::move(new_blk_ptr));
new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
builder.SetInsertPoint(&*new_blk_ptr);
builder.AddBranch(skip_label_id);
func->AddBasicBlock(std::move(new_blk_ptr));
}
// Check for OOB. // Check for OOB.
new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label)); new_blk_ptr = MakeUnique<BasicBlock>(std::move(skip_label));
builder.SetInsertPoint(&*new_blk_ptr); builder.SetInsertPoint(&*new_blk_ptr);
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpUGreaterThanEqual,
param_ids[kByteOffset], init_status_id);
const uint32_t buf_offset_range_id = inst->result_id();
error_blk_id = TakeNextId(); check_label_id = TakeNextId();
merge_blk_id = TakeNextId(); check_label = NewLabel(check_label_id);
merge_label = NewLabel(merge_blk_id); skip_label_id = TakeNextId();
error_label = NewLabel(error_blk_id); skip_label = NewLabel(skip_label_id);
(void)builder.AddConditionalBranch(buf_offset_range_id, error_blk_id,
merge_blk_id, merge_blk_id); inst = builder.AddLoad(GetUintId(), error_var);
error_val_id = inst->result_id();
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpIEqual, error_val_id,
zero_id);
no_error_id = inst->result_id();
(void)builder.AddConditionalBranch(no_error_id, check_label_id, skip_label_id,
skip_label_id);
func->AddBasicBlock(std::move(new_blk_ptr)); func->AddBasicBlock(std::move(new_blk_ptr));
// Error return
new_blk_ptr = MakeUnique<BasicBlock>(std::move(check_label));
builder.SetInsertPoint(&*new_blk_ptr);
{
inst = builder.AddLoad(GetUintId(), init_status_var);
const uint32_t init_status_id = inst->result_id();
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpUGreaterThanEqual,
param_ids[kByteOffset], init_status_id);
const uint32_t buf_offset_range_id = inst->result_id();
const uint32_t error_label_id = TakeNextId();
const uint32_t merge_label_id = TakeNextId();
auto error_label = NewLabel(error_label_id);
auto merge_label = NewLabel(merge_label_id);
(void)builder.AddConditionalBranch(buf_offset_range_id, error_label_id,
merge_label_id, merge_label_id);
func->AddBasicBlock(std::move(new_blk_ptr));
// set error
new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label));
builder.SetInsertPoint(&*new_blk_ptr);
builder.AddStore(error_var, builder.GetUintConstantId(kInstErrorOOB));
builder.AddStore(param5_var, param_ids[kByteOffset]);
builder.AddStore(param6_var, init_status_id);
builder.AddBranch(merge_label_id);
func->AddBasicBlock(std::move(new_blk_ptr));
new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
builder.SetInsertPoint(&*new_blk_ptr);
builder.AddBranch(skip_label_id);
func->AddBasicBlock(std::move(new_blk_ptr));
}
// check for error
new_blk_ptr = MakeUnique<BasicBlock>(std::move(skip_label));
builder.SetInsertPoint(&*new_blk_ptr);
inst = builder.AddLoad(GetUintId(), error_var);
error_val_id = inst->result_id();
inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpINotEqual, zero_id,
error_val_id);
const uint32_t is_error_id = inst->result_id();
const uint32_t error_label_id = TakeNextId();
auto error_label = NewLabel(error_label_id);
const uint32_t merge_label_id = TakeNextId();
auto merge_label = NewLabel(merge_label_id);
(void)builder.AddConditionalBranch(is_error_id, error_label_id,
merge_label_id, merge_label_id);
func->AddBasicBlock(std::move(new_blk_ptr));
new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label)); new_blk_ptr = MakeUnique<BasicBlock>(std::move(error_label));
builder.SetInsertPoint(&*new_blk_ptr); builder.SetInsertPoint(&*new_blk_ptr);
// error output
inst = builder.AddLoad(GetUintId(), param5_var);
const uint32_t param5_val_id = inst->result_id();
inst = builder.AddLoad(GetUintId(), param6_var);
const uint32_t param6_val_id = inst->result_id();
GenDebugStreamWrite( GenDebugStreamWrite(
param_ids[kShaderId], param_ids[kInstructionIndex], param_ids[kStageInfo], param_ids[kShaderId], param_ids[kInstructionIndex], param_ids[kStageInfo],
{builder.GetUintConstantId(kInstErrorOOB), param_ids[kDescSet], {error_val_id, param_ids[kDescSet], param_ids[kDescBinding],
param_ids[kDescBinding], param_ids[kDescIndex], param_ids[kByteOffset], param_ids[kDescIndex], param5_val_id, param6_val_id},
init_status_id},
&builder); &builder);
(void)builder.AddUnaryOp(0, spv::Op::OpReturnValue, false_id); (void)builder.AddUnaryOp(0, spv::Op::OpReturnValue, false_id);
func->AddBasicBlock(std::move(new_blk_ptr)); func->AddBasicBlock(std::move(new_blk_ptr));

View File

@ -135,19 +135,32 @@ static const std::string kCheckDesc = R"(
; CHECK: [[di_shader_id:%\w+]] = OpFunctionParameter %uint ; CHECK: [[di_shader_id:%\w+]] = OpFunctionParameter %uint
; CHECK: [[di_line:%\w+]] = OpFunctionParameter %uint ; CHECK: [[di_line:%\w+]] = OpFunctionParameter %uint
; CHECK: [[di_stage_info:%\w+]] = OpFunctionParameter %v4uint ; CHECK: [[di_stage_info:%\w+]] = OpFunctionParameter %v4uint
; CHECK: [[di_desc_set_idx:%\w+]] = OpFunctionParameter %uint ; CHECK: [[di_desc_set:%\w+]] = OpFunctionParameter %uint
; CHECK: [[di_binding_idx:%\w+]] = OpFunctionParameter %uint ; CHECK: [[di_binding:%\w+]] = OpFunctionParameter %uint
; CHECK: [[di_desc_idx:%\w+]] = OpFunctionParameter %uint ; CHECK: [[di_desc_idx:%\w+]] = OpFunctionParameter %uint
; CHECK: [[di_byte_offset:%\w+]] = OpFunctionParameter %uint ; CHECK: [[di_byte_offset:%\w+]] = OpFunctionParameter %uint
; CHECK: {{%\w+}} = OpLabel ; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpUGreaterThanEqual %bool [[di_desc_set_idx]] %uint_32 ; CHECK: [[di_error:%\w+]] = OpVariable %_ptr_Function_uint Function %uint_0
; CHECK: [[di_param5:%\w+]] = OpVariable %_ptr_Function_uint Function %uint_0
; CHECK: [[di_param6:%\w+]] = OpVariable %_ptr_Function_uint Function %uint_0
; CHECK: [[di_num_bindings:%\w+]] = OpVariable %_ptr_Function_uint Function %uint_0
; CHECK: [[di_init_status:%\w+]] = OpVariable %_ptr_Function_uint Function %uint_0
; CHECK: [[di_desc_set_ptr:%\w+]] = OpVariable %_ptr_Function__ptr_PhysicalStorageBuffer_inst_bindless_DescriptorSetData Function
; CHECK: {{%\w+}} = OpUGreaterThanEqual %bool [[di_desc_set]] %uint_32
; CHECK: OpSelectionMerge {{%\w+}} None ; CHECK: OpSelectionMerge {{%\w+}} None
; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} ; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
; CHECK: {{%\w+}} = OpLabel ; CHECK: {{%\w+}} = OpLabel
; CHECK: OpReturnValue %false ; CHECK: OpStore [[di_error]] %uint_1
; CHECK: OpBranch {{%\w+}}
; CHECK: {{%\w+}} = OpLabel ; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_inst_bindless_DescriptorSetData %inst_bindless_input_buffer %uint_0 [[di_desc_set_idx]] ; CHECK: {{%\w+}} = OpLoad %uint [[di_error]]
; CHECK: {{%\w+}} = OpIEqual %bool {{%\w+}} %uint_0
; CHECK: OpSelectionMerge {{%\w+}} None
; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_inst_bindless_DescriptorSetData %inst_bindless_input_buffer %uint_0 [[di_desc_set]]
; CHECK: {{%\w+}} = OpLoad %_ptr_PhysicalStorageBuffer_inst_bindless_DescriptorSetData {{%\w+}} ; CHECK: {{%\w+}} = OpLoad %_ptr_PhysicalStorageBuffer_inst_bindless_DescriptorSetData {{%\w+}}
; CHECK: OpStore [[di_desc_set_ptr]] {{%\w+}}
; CHECK: {{%\w+}} = OpBitcast %v2uint {{%\w+}} ; CHECK: {{%\w+}} = OpBitcast %v2uint {{%\w+}}
; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0 ; CHECK: {{%\w+}} = OpCompositeExtract %uint {{%\w+}} 0
; CHECK: {{%\w+}} = OpIEqual %bool {{%\w+}} %uint_0 ; CHECK: {{%\w+}} = OpIEqual %bool {{%\w+}} %uint_0
@ -157,44 +170,96 @@ static const std::string kCheckDesc = R"(
; CHECK: OpSelectionMerge {{%\w+}} None ; CHECK: OpSelectionMerge {{%\w+}} None
; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} ; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
; CHECK: {{%\w+}} = OpLabel ; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpFunctionCall %void %inst_bindless_stream_write_6 [[di_shader_id]] [[di_line]] [[di_stage_info]] %uint_1 [[di_desc_set_idx]] [[di_binding_idx]] [[di_desc_idx]] %uint_0 %uint_0 ; CHECK: OpStore [[di_error]] %uint_1
; CHECK: OpReturnValue %false ; CHECK: OpBranch {{%\w+}}
; CHECK: {{%\w+}} = OpLabel ; CHECK: {{%\w+}} = OpLabel
; CHECK: OpBranch {{%\w+}}
; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpLoad %uint [[di_error]]
; CHECK: {{%\w+}} = OpIEqual %bool {{%\w+}} %uint_0
; CHECK: OpSelectionMerge {{%\w+}} None
; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpLoad %_ptr_PhysicalStorageBuffer_inst_bindless_DescriptorSetData [[di_desc_set_ptr]]
; CHECK: {{%\w+}} = OpAccessChain %_ptr_PhysicalStorageBuffer_uint {{%\w+}} %uint_0 ; CHECK: {{%\w+}} = OpAccessChain %_ptr_PhysicalStorageBuffer_uint {{%\w+}} %uint_0
; CHECK: [[di_num_bindings:%\w+]] = OpLoad %uint {{%\w+}} Aligned 8 ; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}} Aligned 8
; CHECK: {{%\w+}} = OpUGreaterThanEqual %bool [[di_binding_idx]] [[di_num_bindings]] ; CHECK: OpStore [[di_num_bindings]] {{%\w+}}
; CHECK: {{%\w+}} = OpUGreaterThanEqual %bool [[di_binding]] {{%\w+}}
; CHECK: OpSelectionMerge {{%\w+}} None ; CHECK: OpSelectionMerge {{%\w+}} None
; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} ; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
; CHECK: {{%\w+}} = OpLabel ; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpFunctionCall %void %inst_bindless_stream_write_6 [[di_shader_id]] [[di_line]] [[di_stage_info]] %uint_1 [[di_desc_set_idx]] [[di_binding_idx]] [[di_desc_idx]] %uint_0 %uint_0 ; CHECK: OpStore [[di_error]] %uint_1
; CHECK: OpReturnValue %false ; CHECK: OpBranch {{%\w+}}
; CHECK: {{%\w+}} = OpLabel ; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpAccessChain %_ptr_PhysicalStorageBuffer_uint {{%\w+}} %uint_1 [[di_binding_idx]] ; CHECK: OpBranch {{%\w+}}
; CHECK: [[di_desc_array_len:%\w+]] = OpLoad %uint {{%\w+}} Aligned 4 ; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpUGreaterThanEqual %bool [[di_desc_idx]] [[di_desc_array_len]] ; CHECK: {{%\w+}} = OpLoad %uint [[di_error]]
; CHECK: {{%\w+}} = OpIEqual %bool {{%\w+}} %uint_0
; CHECK: OpSelectionMerge {{%\w+}} None ; CHECK: OpSelectionMerge {{%\w+}} None
; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} ; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
; CHECK: {{%\w+}} = OpLabel ; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpFunctionCall %void %inst_bindless_stream_write_6 [[di_shader_id]] [[di_line]] [[di_stage_info]] %uint_1 [[di_desc_set_idx]] [[di_binding_idx]] [[di_desc_idx]] [[di_desc_array_len]] %uint_0 ; CHECK: {{%\w+}} = OpLoad %_ptr_PhysicalStorageBuffer_inst_bindless_DescriptorSetData [[di_desc_set_ptr]]
; CHECK: OpReturnValue %false ; CHECK: {{%\w+}} = OpAccessChain %_ptr_PhysicalStorageBuffer_uint {{%\w+}} %uint_1 [[di_binding]]
; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}} Aligned 4
; CHECK: {{%\w+}} = OpUGreaterThanEqual %bool [[di_desc_idx]] {{%\w+}}
; CHECK: OpSelectionMerge {{%\w+}} None
; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
; CHECK: {{%\w+}} = OpLabel ; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} {{%\w+}} ; CHECK: OpStore [[di_error]] %uint_1
; CHECK: OpStore [[di_param5]] {{%\w+}}
; CHECK: OpBranch {{%\w+}}
; CHECK: {{%\w+}} = OpLabel
; CHECK: OpBranch {{%\w+}}
; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpLoad %uint [[di_error]]
; CHECK: {{%\w+}} = OpLoad %uint [[di_error]]
; CHECK: {{%\w+}} = OpIEqual %bool %uint_0 {{%\w+}}
; CHECK: OpSelectionMerge {{%\w+}} None
; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpLoad %_ptr_PhysicalStorageBuffer_inst_bindless_DescriptorSetData [[di_desc_set_ptr]]
; CHECK: {{%\w+}} = OpLoad %uint [[di_num_bindings]]
; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} [[di_binding]]
; CHECK: {{%\w+}} = OpAccessChain %_ptr_PhysicalStorageBuffer_uint {{%\w+}} %uint_1 {{%\w+}} ; CHECK: {{%\w+}} = OpAccessChain %_ptr_PhysicalStorageBuffer_uint {{%\w+}} %uint_1 {{%\w+}}
; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}} Aligned 4 ; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}} Aligned 4
; CHECK: {{%\w+}} = OpIAdd %uint {{%\w+}} [[di_desc_idx]]
; CHECK: {{%\w+}} = OpAccessChain %_ptr_PhysicalStorageBuffer_uint {{%\w+}} %uint_1 {{%\w+}} ; CHECK: {{%\w+}} = OpAccessChain %_ptr_PhysicalStorageBuffer_uint {{%\w+}} %uint_1 {{%\w+}}
; CHECK: [[di_init_status:%\w+]] = OpLoad %uint {{%\w+}} Aligned 4 ; CHECK: {{%\w+}} = OpLoad %uint {{%\w+}} Aligned 4
; CHECK: {{%\w+}} = OpIEqual %bool [[di_init_status]] %uint_0 ; CHECK: OpStore [[di_init_status]] {{%\w+}}
; CHECK: {{%\w+}} = OpIEqual %bool {{%\w+}} %uint_0
; CHECK: OpSelectionMerge {{%\w+}} None ; CHECK: OpSelectionMerge {{%\w+}} None
; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} ; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
; CHECK: {{%\w+}} = OpLabel ; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpFunctionCall %void %inst_bindless_stream_write_6 [[di_shader_id]] [[di_line]] [[di_stage_info]] %uint_2 [[di_desc_set_idx]] [[di_binding_idx]] [[di_desc_idx]] %uint_0 %uint_0 ; CHECK: OpStore [[di_error]] %uint_2
; CHECK: OpReturnValue %false ; CHECK: OpBranch {{%\w+}}
; CHECK: {{%\w+}} = OpLabel ; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpUGreaterThanEqual %bool {{%\w+}} {{%\w+}} ; CHECK: OpBranch {{%\w+}}
; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpLoad %uint [[di_error]]
; CHECK: {{%\w+}} = OpIEqual %bool {{%\w+}} %uint_0
; CHECK: OpSelectionMerge {{%\w+}} None ; CHECK: OpSelectionMerge {{%\w+}} None
; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}} ; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
; CHECK: {{%\w+}} = OpLabel ; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpFunctionCall %void %inst_bindless_stream_write_6 [[di_shader_id]] [[di_line]] [[di_stage_info]] %uint_4 [[di_desc_set_idx]] [[di_binding_idx]] [[di_desc_idx]] [[di_byte_offset]] [[di_init_status]] ; CHECK: {{%\w+}} = OpLoad %uint [[di_init_status]]
; CHECK: {{%\w+}} = OpUGreaterThanEqual %bool [[di_byte_offset]] {{%\w+}}
; CHECK: OpSelectionMerge {{%\w+}} None
; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
; CHECK: {{%\w+}} = OpLabel
; CHECK: OpStore [[di_error]] %uint_4
; CHECK: OpStore [[di_param5]] [[di_byte_offset]]
; CHECK: OpStore [[di_param6]] {{%\w+}}
; CHECK: OpBranch {{%\w+}}
; CHECK: {{%\w+}} = OpLabel
; CHECK: OpBranch {{%\w+}}
; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpLoad %uint [[di_error]]
; CHECK: {{%\w+}} = OpINotEqual %bool %uint_0 {{%\w+}}
; CHECK: OpSelectionMerge {{%\w+}} None
; CHECK: OpBranchConditional {{%\w+}} {{%\w+}} {{%\w+}}
; CHECK: {{%\w+}} = OpLabel
; CHECK: {{%\w+}} = OpLoad %uint [[di_param5]]
; CHECK: {{%\w+}} = OpLoad %uint [[di_param6]]
; CHECK: {{%\w+}} = OpFunctionCall %void %inst_bindless_stream_write_6 [[di_shader_id]] [[di_line]] [[di_stage_info]] {{%\w+}} [[di_desc_set]] [[di_binding]] [[di_desc_idx]] {{%\w+}} {{%\w+}}
; CHECK: OpReturnValue %false ; CHECK: OpReturnValue %false
; CHECK: {{%\w+}} = OpLabel ; CHECK: {{%\w+}} = OpLabel
; CHECK: OpReturnValue %true ; CHECK: OpReturnValue %true
@ -4377,7 +4442,7 @@ TEST_F(InstBindlessTest, UniformMatrixRefRowMajor) {
;CHECK: {{%\w+}} = OpLabel ;CHECK: {{%\w+}} = OpLabel
;CHECK: [[phi_result]] = OpPhi %float [[load_result]] {{%\w+}} [[null_float]] {{%\w+}} ;CHECK: [[phi_result]] = OpPhi %float [[load_result]] {{%\w+}} [[null_float]] {{%\w+}}
OpStore %v_vtxResult %21 OpStore %v_vtxResult %21
;CHECK-NOT: OpStore %v_vtxResult %21 ;CHECK-NOT: OpStore %v_vtxResult %21$
;CHECK: OpStore %v_vtxResult [[phi_result]] ;CHECK: OpStore %v_vtxResult [[phi_result]]
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd
@ -4493,7 +4558,7 @@ TEST_F(InstBindlessTest, UniformMatrixRefColumnMajor) {
;CHECK: {{%\w+}} = OpLabel ;CHECK: {{%\w+}} = OpLabel
;CHECK: [[phi_result]] = OpPhi %float [[load_result]] {{%\w+}} [[null_float]] {{%\w+}} ;CHECK: [[phi_result]] = OpPhi %float [[load_result]] {{%\w+}} [[null_float]] {{%\w+}}
OpStore %v_vtxResult %21 OpStore %v_vtxResult %21
;CHECK-NOT: OpStore %v_vtxResult %21 ;CHECK-NOT: OpStore %v_vtxResult %21$
;CHECK: OpStore %v_vtxResult [[phi_result]] ;CHECK: OpStore %v_vtxResult [[phi_result]]
OpReturn OpReturn
OpFunctionEnd OpFunctionEnd