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;
}
// 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.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;

View File

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

View File

@ -3744,6 +3744,7 @@ void Compiler::analyze_variable_scope(SPIRFunction &entry, AnalyzeVariableScopeA
DominatorBuilder builder(cfg);
auto &blocks = var.second;
auto &type = expression_type(var.first);
BlockID potential_continue_block = 0;
// Figure out which block is dominating all accesses of those variables.
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
// candidate, signal that by setting block to -1u.
auto &potential = potential_loop_variables[var.first];
if (potential == 0)
potential = block;
if (potential_continue_block == 0)
potential_continue_block = block;
else
potential = ~(0u);
potential_continue_block = ~(0u);
}
}
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.
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
// actually need to be preserved across loop iterations. We can express this by adding
// 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
flushed_phi_variables.clear();
current_emitting_switch_stack.clear();
reset_name_caches();
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 ...
// 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,
// 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.
if (current_emitting_switch && is_loop_break(to) &&
current_emitting_switch->loop_dominator != BlockID(SPIRBlock::NoDominator) &&
get<SPIRBlock>(current_emitting_switch->loop_dominator).merge_block == to)
if (is_loop_break(to))
{
if (!current_emitting_switch->need_ladder_break)
for (size_t n = current_emitting_switch_stack.size(); n; n--)
{
force_recompile();
current_emitting_switch->need_ladder_break = true;
}
auto *current_emitting_switch = current_emitting_switch_stack[n - 1];
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;");
}
@ -15594,8 +15607,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
else if (type.basetype == SPIRType::Short)
label_suffix = backend.int16_t_literal_suffix;
SPIRBlock *old_emitting_switch = current_emitting_switch;
current_emitting_switch = &block;
current_emitting_switch_stack.push_back(&block);
if (block.need_ladder_break)
statement("bool _", block.self, "_ladder_break = false;");
@ -15880,7 +15892,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
end_scope();
}
current_emitting_switch = old_emitting_switch;
current_emitting_switch_stack.pop_back();
break;
}

View File

@ -364,7 +364,7 @@ protected:
virtual void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags);
SPIRBlock *current_emitting_block = nullptr;
SPIRBlock *current_emitting_switch = nullptr;
SmallVector<SPIRBlock *> current_emitting_switch_stack;
bool current_emitting_switch_fallthrough = false;
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;
}
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)
{
if (func.self != ir.default_entry_point)
add_function_overload(func);
auto &execution = get_entry_point();
// Avoid shadow declarations.
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 (execution.model == ExecutionModelVertex)
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.");
decl += get_inner_entry_point_name();
processing_entry_point = true;
}
else
@ -2555,7 +2568,13 @@ void CompilerHLSL::emit_hlsl_entry_point()
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();
bool legacy = hlsl_options.shader_model <= 30;
@ -2728,12 +2747,12 @@ void CompilerHLSL::emit_hlsl_entry_point()
});
// Run the shader.
if (execution.model == ExecutionModelVertex)
statement("vert_main();");
else if (execution.model == ExecutionModelFragment)
statement("frag_main();");
else if (execution.model == ExecutionModelGLCompute)
statement("comp_main();");
if (execution.model == ExecutionModelVertex ||
execution.model == ExecutionModelFragment ||
execution.model == ExecutionModelGLCompute)
{
statement(get_inner_entry_point_name(), "();");
}
else
SPIRV_CROSS_THROW("Unsupported shader stage.");
@ -4728,9 +4747,9 @@ void CompilerHLSL::emit_subgroup_op(const Instruction &i)
case OpGroupNonUniformBallotBitCount:
{
auto operation = static_cast<GroupOperation>(ops[3]);
bool forward = should_forward(ops[4]);
if (operation == GroupOperationReduce)
{
bool forward = should_forward(ops[4]);
auto left = join("countbits(", to_enclosed_expression(ops[4]), ".x) + countbits(",
to_enclosed_expression(ops[4]), ".y)");
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]);
}
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)
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
SPIRV_CROSS_THROW("Invalid BitCount operation.");
break;

View File

@ -137,6 +137,9 @@ public:
// If add_vertex_attribute_remap is used and this feature is used,
// the semantic name will be queried once per active location.
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_)
@ -374,6 +377,8 @@ private:
bool builtin_translates_to_nonarray(spv::BuiltIn builtin) const override;
std::vector<TypeID> composite_selection_workaround_types;
std::string get_inner_entry_point_name() const;
};
} // namespace SPIRV_CROSS_NAMESPACE

View File

@ -1020,7 +1020,16 @@ void Parser::parse(const Instruction &instruction)
}
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->condition = 0;
current_block->true_block = 0;