mirror of https://github.com/bkaradzic/bgfx
Updated spirv-cross.
This commit is contained in:
parent
758d02db1e
commit
67b2f1e2bf
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 = █
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue