Updated spirv-cross.

This commit is contained in:
Бранимир Караџић
2022-07-29 21:42:07 -07:00
parent 758d02db1e
commit 67b2f1e2bf
8 changed files with 142 additions and 38 deletions

View File

@@ -1348,6 +1348,10 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
build_dummy_sampler = true; build_dummy_sampler = true;
} }
// If we're explicitly renaming, we probably want that name to be output.
if (!args.entry_point_rename.empty())
hlsl_opts.use_entry_point_name = true;
hlsl_opts.support_nonzero_base_vertex_base_instance = args.hlsl_support_nonzero_base; hlsl_opts.support_nonzero_base_vertex_base_instance = args.hlsl_support_nonzero_base;
hlsl_opts.force_storage_buffer_as_uav = args.hlsl_force_storage_buffer_as_uav; hlsl_opts.force_storage_buffer_as_uav = args.hlsl_force_storage_buffer_as_uav;
hlsl_opts.nonwritable_uav_texture_as_srv = args.hlsl_nonwritable_uav_texture_as_srv; hlsl_opts.nonwritable_uav_texture_as_srv = args.hlsl_nonwritable_uav_texture_as_srv;

View File

@@ -59,6 +59,11 @@ public:
return 0; return 0;
} }
bool is_reachable(uint32_t block) const
{
return visit_order.count(block) != 0;
}
uint32_t get_visit_order(uint32_t block) const uint32_t get_visit_order(uint32_t block) const
{ {
auto itr = visit_order.find(block); auto itr = visit_order.find(block);

View File

@@ -3744,6 +3744,7 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry, AnalyzeVariableScopeA
DominatorBuilder builder(cfg); DominatorBuilder builder(cfg);
auto &blocks = var.second; auto &blocks = var.second;
auto &type = expression_type(var.first); auto &type = expression_type(var.first);
BlockID potential_continue_block = 0;
// Figure out which block is dominating all accesses of those variables. // Figure out which block is dominating all accesses of those variables.
for (auto &block : blocks) for (auto &block : blocks)
@@ -3765,14 +3766,13 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry, AnalyzeVariableScopeA
{ {
// The variable is used in multiple continue blocks, this is not a loop // The variable is used in multiple continue blocks, this is not a loop
// candidate, signal that by setting block to -1u. // candidate, signal that by setting block to -1u.
auto &potential = potential_loop_variables[var.first]; if (potential_continue_block == 0)
potential_continue_block = block;
if (potential == 0)
potential = block;
else else
potential = ~(0u); potential_continue_block = ~(0u);
} }
} }
builder.add_block(block); builder.add_block(block);
} }
@@ -3781,6 +3781,34 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry, AnalyzeVariableScopeA
// Add it to a per-block list of variables. // Add it to a per-block list of variables.
BlockID dominating_block = builder.get_dominator(); BlockID dominating_block = builder.get_dominator();
if (dominating_block && potential_continue_block != 0 && potential_continue_block != ~0u)
{
auto &inner_block = get<SPIRBlock>(dominating_block);
BlockID merge_candidate = 0;
// Analyze the dominator. If it lives in a different loop scope than the candidate continue
// block, reject the loop variable candidate.
if (inner_block.merge == SPIRBlock::MergeLoop)
merge_candidate = inner_block.merge_block;
else if (inner_block.loop_dominator != SPIRBlock::NoDominator)
merge_candidate = get<SPIRBlock>(inner_block.loop_dominator).merge_block;
if (merge_candidate != 0 && cfg.is_reachable(merge_candidate))
{
// If the merge block has a higher post-visit order, we know that continue candidate
// cannot reach the merge block, and we have two separate scopes.
if (!cfg.is_reachable(potential_continue_block) ||
cfg.get_visit_order(merge_candidate) > cfg.get_visit_order(potential_continue_block))
{
potential_continue_block = 0;
}
}
}
if (potential_continue_block != 0 && potential_continue_block != ~0u)
potential_loop_variables[var.first] = potential_continue_block;
// For variables whose dominating block is inside a loop, there is a risk that these variables // For variables whose dominating block is inside a loop, there is a risk that these variables
// actually need to be preserved across loop iterations. We can express this by adding // actually need to be preserved across loop iterations. We can express this by adding
// a "read" access to the loop header. // a "read" access to the loop header.

View File

@@ -327,6 +327,8 @@ void CompilerGLSL::reset(uint32_t iteration_count)
// Ensure that we declare phi-variable copies even if the original declaration isn't deferred // Ensure that we declare phi-variable copies even if the original declaration isn't deferred
flushed_phi_variables.clear(); flushed_phi_variables.clear();
current_emitting_switch_stack.clear();
reset_name_caches(); reset_name_caches();
ir.for_each_typed_id<SPIRFunction>([&](uint32_t, SPIRFunction &func) { ir.for_each_typed_id<SPIRFunction>([&](uint32_t, SPIRFunction &func) {
@@ -14895,21 +14897,32 @@ void CompilerGLSL::branch(BlockID from, BlockID to)
// - Break merge target all at once ... // - Break merge target all at once ...
// Very dirty workaround. // Very dirty workaround.
// Switch constructs are able to break, but they cannot break out of a loop at the same time. // Switch constructs are able to break, but they cannot break out of a loop at the same time,
// yet SPIR-V allows it.
// Only sensible solution is to make a ladder variable, which we declare at the top of the switch block, // Only sensible solution is to make a ladder variable, which we declare at the top of the switch block,
// write to the ladder here, and defer the break. // write to the ladder here, and defer the break.
// The loop we're breaking out of must dominate the switch block, or there is no ladder breaking case. // The loop we're breaking out of must dominate the switch block, or there is no ladder breaking case.
if (current_emitting_switch && is_loop_break(to) && if (is_loop_break(to))
current_emitting_switch->loop_dominator != BlockID(SPIRBlock::NoDominator) &&
get<SPIRBlock>(current_emitting_switch->loop_dominator).merge_block == to)
{ {
if (!current_emitting_switch->need_ladder_break) for (size_t n = current_emitting_switch_stack.size(); n; n--)
{ {
force_recompile(); auto *current_emitting_switch = current_emitting_switch_stack[n - 1];
current_emitting_switch->need_ladder_break = true;
}
statement("_", current_emitting_switch->self, "_ladder_break = true;"); if (current_emitting_switch &&
current_emitting_switch->loop_dominator != BlockID(SPIRBlock::NoDominator) &&
get<SPIRBlock>(current_emitting_switch->loop_dominator).merge_block == to)
{
if (!current_emitting_switch->need_ladder_break)
{
force_recompile();
current_emitting_switch->need_ladder_break = true;
}
statement("_", current_emitting_switch->self, "_ladder_break = true;");
}
else
break;
}
} }
statement("break;"); statement("break;");
} }
@@ -15594,8 +15607,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
else if (type.basetype == SPIRType::Short) else if (type.basetype == SPIRType::Short)
label_suffix = backend.int16_t_literal_suffix; label_suffix = backend.int16_t_literal_suffix;
SPIRBlock *old_emitting_switch = current_emitting_switch; current_emitting_switch_stack.push_back(&block);
current_emitting_switch = &block;
if (block.need_ladder_break) if (block.need_ladder_break)
statement("bool _", block.self, "_ladder_break = false;"); statement("bool _", block.self, "_ladder_break = false;");
@@ -15880,7 +15892,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
end_scope(); end_scope();
} }
current_emitting_switch = old_emitting_switch; current_emitting_switch_stack.pop_back();
break; break;
} }

View File

@@ -364,7 +364,7 @@ protected:
virtual void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags); virtual void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags);
SPIRBlock *current_emitting_block = nullptr; SPIRBlock *current_emitting_block = nullptr;
SPIRBlock *current_emitting_switch = nullptr; SmallVector<SPIRBlock *> current_emitting_switch_stack;
bool current_emitting_switch_fallthrough = false; bool current_emitting_switch_fallthrough = false;
virtual void emit_instruction(const Instruction &instr); virtual void emit_instruction(const Instruction &instr);

View File

@@ -2404,12 +2404,32 @@ string CompilerHLSL::to_func_call_arg(const SPIRFunction::Parameter &arg, uint32
return arg_str; return arg_str;
} }
string CompilerHLSL::get_inner_entry_point_name() const
{
auto &execution = get_entry_point();
if (hlsl_options.use_entry_point_name)
{
auto name = join(execution.name, "_inner");
ParsedIR::sanitize_underscores(name);
return name;
}
if (execution.model == ExecutionModelVertex)
return "vert_main";
else if (execution.model == ExecutionModelFragment)
return "frag_main";
else if (execution.model == ExecutionModelGLCompute)
return "comp_main";
else
SPIRV_CROSS_THROW("Unsupported execution model.");
}
void CompilerHLSL::emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) void CompilerHLSL::emit_function_prototype(SPIRFunction &func, const Bitset &return_flags)
{ {
if (func.self != ir.default_entry_point) if (func.self != ir.default_entry_point)
add_function_overload(func); add_function_overload(func);
auto &execution = get_entry_point();
// Avoid shadow declarations. // Avoid shadow declarations.
local_variable_names = resource_names; local_variable_names = resource_names;
@@ -2430,14 +2450,7 @@ void CompilerHLSL::emit_function_prototype(SPIRFunction &func, const Bitset &ret
if (func.self == ir.default_entry_point) if (func.self == ir.default_entry_point)
{ {
if (execution.model == ExecutionModelVertex) decl += get_inner_entry_point_name();
decl += "vert_main";
else if (execution.model == ExecutionModelFragment)
decl += "frag_main";
else if (execution.model == ExecutionModelGLCompute)
decl += "comp_main";
else
SPIRV_CROSS_THROW("Unsupported execution model.");
processing_entry_point = true; processing_entry_point = true;
} }
else else
@@ -2555,7 +2568,13 @@ void CompilerHLSL::emit_hlsl_entry_point()
break; break;
} }
statement(require_output ? "SPIRV_Cross_Output " : "void ", "main(", merge(arguments), ")"); const char *entry_point_name;
if (hlsl_options.use_entry_point_name)
entry_point_name = get_entry_point().name.c_str();
else
entry_point_name = "main";
statement(require_output ? "SPIRV_Cross_Output " : "void ", entry_point_name, "(", merge(arguments), ")");
begin_scope(); begin_scope();
bool legacy = hlsl_options.shader_model <= 30; bool legacy = hlsl_options.shader_model <= 30;
@@ -2728,12 +2747,12 @@ void CompilerHLSL::emit_hlsl_entry_point()
}); });
// Run the shader. // Run the shader.
if (execution.model == ExecutionModelVertex) if (execution.model == ExecutionModelVertex ||
statement("vert_main();"); execution.model == ExecutionModelFragment ||
else if (execution.model == ExecutionModelFragment) execution.model == ExecutionModelGLCompute)
statement("frag_main();"); {
else if (execution.model == ExecutionModelGLCompute) statement(get_inner_entry_point_name(), "();");
statement("comp_main();"); }
else else
SPIRV_CROSS_THROW("Unsupported shader stage."); SPIRV_CROSS_THROW("Unsupported shader stage.");
@@ -4728,9 +4747,9 @@ void CompilerHLSL::emit_subgroup_op(const Instruction &i)
case OpGroupNonUniformBallotBitCount: case OpGroupNonUniformBallotBitCount:
{ {
auto operation = static_cast<GroupOperation>(ops[3]); auto operation = static_cast<GroupOperation>(ops[3]);
bool forward = should_forward(ops[4]);
if (operation == GroupOperationReduce) if (operation == GroupOperationReduce)
{ {
bool forward = should_forward(ops[4]);
auto left = join("countbits(", to_enclosed_expression(ops[4]), ".x) + countbits(", auto left = join("countbits(", to_enclosed_expression(ops[4]), ".x) + countbits(",
to_enclosed_expression(ops[4]), ".y)"); to_enclosed_expression(ops[4]), ".y)");
auto right = join("countbits(", to_enclosed_expression(ops[4]), ".z) + countbits(", auto right = join("countbits(", to_enclosed_expression(ops[4]), ".z) + countbits(",
@@ -4739,9 +4758,31 @@ void CompilerHLSL::emit_subgroup_op(const Instruction &i)
inherit_expression_dependencies(id, ops[4]); inherit_expression_dependencies(id, ops[4]);
} }
else if (operation == GroupOperationInclusiveScan) else if (operation == GroupOperationInclusiveScan)
SPIRV_CROSS_THROW("Cannot trivially implement BallotBitCount Inclusive Scan in HLSL."); {
auto left = join("countbits(", to_enclosed_expression(ops[4]), ".x & gl_SubgroupLeMask.x) + countbits(",
to_enclosed_expression(ops[4]), ".y & gl_SubgroupLeMask.y)");
auto right = join("countbits(", to_enclosed_expression(ops[4]), ".z & gl_SubgroupLeMask.z) + countbits(",
to_enclosed_expression(ops[4]), ".w & gl_SubgroupLeMask.w)");
emit_op(result_type, id, join(left, " + ", right), forward);
if (!active_input_builtins.get(BuiltInSubgroupLeMask))
{
active_input_builtins.set(BuiltInSubgroupLeMask);
force_recompile_guarantee_forward_progress();
}
}
else if (operation == GroupOperationExclusiveScan) else if (operation == GroupOperationExclusiveScan)
SPIRV_CROSS_THROW("Cannot trivially implement BallotBitCount Exclusive Scan in HLSL."); {
auto left = join("countbits(", to_enclosed_expression(ops[4]), ".x & gl_SubgroupLtMask.x) + countbits(",
to_enclosed_expression(ops[4]), ".y & gl_SubgroupLtMask.y)");
auto right = join("countbits(", to_enclosed_expression(ops[4]), ".z & gl_SubgroupLtMask.z) + countbits(",
to_enclosed_expression(ops[4]), ".w & gl_SubgroupLtMask.w)");
emit_op(result_type, id, join(left, " + ", right), forward);
if (!active_input_builtins.get(BuiltInSubgroupLtMask))
{
active_input_builtins.set(BuiltInSubgroupLtMask);
force_recompile_guarantee_forward_progress();
}
}
else else
SPIRV_CROSS_THROW("Invalid BitCount operation."); SPIRV_CROSS_THROW("Invalid BitCount operation.");
break; break;

View File

@@ -137,6 +137,9 @@ public:
// If add_vertex_attribute_remap is used and this feature is used, // If add_vertex_attribute_remap is used and this feature is used,
// the semantic name will be queried once per active location. // the semantic name will be queried once per active location.
bool flatten_matrix_vertex_input_semantics = false; bool flatten_matrix_vertex_input_semantics = false;
// Rather than emitting main() for the entry point, use the name in SPIR-V.
bool use_entry_point_name = false;
}; };
explicit CompilerHLSL(std::vector<uint32_t> spirv_) explicit CompilerHLSL(std::vector<uint32_t> spirv_)
@@ -374,6 +377,8 @@ private:
bool builtin_translates_to_nonarray(spv::BuiltIn builtin) const override; bool builtin_translates_to_nonarray(spv::BuiltIn builtin) const override;
std::vector<TypeID> composite_selection_workaround_types; std::vector<TypeID> composite_selection_workaround_types;
std::string get_inner_entry_point_name() const;
}; };
} // namespace SPIRV_CROSS_NAMESPACE } // namespace SPIRV_CROSS_NAMESPACE

View File

@@ -1020,7 +1020,16 @@ void Parser::parse(const Instruction &instruction)
} }
else else
{ {
ir.block_meta[current_block->next_block] &= ~ParsedIR::BLOCK_META_SELECTION_MERGE_BIT; // Collapse loops if we have to.
bool collapsed_loop = current_block->true_block == current_block->merge_block &&
current_block->merge == SPIRBlock::MergeLoop;
if (collapsed_loop)
{
ir.block_meta[current_block->merge_block] &= ~ParsedIR::BLOCK_META_LOOP_MERGE_BIT;
ir.block_meta[current_block->continue_block] &= ~ParsedIR::BLOCK_META_CONTINUE_BIT;
}
current_block->next_block = current_block->true_block; current_block->next_block = current_block->true_block;
current_block->condition = 0; current_block->condition = 0;
current_block->true_block = 0; current_block->true_block = 0;