Updated spirv-cross.

This commit is contained in:
Бранимир Караџић 2022-05-21 18:47:14 -07:00
parent 6bbda98efa
commit f294ee6858
4 changed files with 128 additions and 10 deletions

View File

@ -1070,6 +1070,18 @@ static ExecutionModel stage_to_execution_model(const std::string &stage)
return ExecutionModelTessellationEvaluation;
else if (stage == "geom")
return ExecutionModelGeometry;
else if (stage == "rgen")
return ExecutionModelRayGenerationKHR;
else if (stage == "rint")
return ExecutionModelIntersectionKHR;
else if (stage == "rahit")
return ExecutionModelAnyHitKHR;
else if (stage == "rchit")
return ExecutionModelClosestHitKHR;
else if (stage == "rmiss")
return ExecutionModelMissKHR;
else if (stage == "rcall")
return ExecutionModelCallableKHR;
else
SPIRV_CROSS_THROW("Invalid stage.");
}

View File

@ -316,6 +316,7 @@ void CompilerGLSL::reset(uint32_t iteration_count)
// Clear invalid expression tracking.
invalid_expressions.clear();
composite_insert_overwritten.clear();
current_function = nullptr;
// Clear temporary usage tracking.
@ -4311,7 +4312,8 @@ void CompilerGLSL::force_temporary_and_recompile(uint32_t id)
uint32_t CompilerGLSL::consume_temporary_in_precision_context(uint32_t type_id, uint32_t id, Options::Precision precision)
{
// Constants do not have innate precision.
if (ir.ids[id].get_type() == TypeConstant || ir.ids[id].get_type() == TypeConstantOp)
auto handle_type = ir.ids[id].get_type();
if (handle_type == TypeConstant || handle_type == TypeConstantOp || handle_type == TypeUndef)
return id;
// Ignore anything that isn't 32-bit values.
@ -4381,6 +4383,11 @@ void CompilerGLSL::handle_invalid_expression(uint32_t id)
// This means we need another pass at compilation, but next time,
// force temporary variables so that they cannot be invalidated.
force_temporary_and_recompile(id);
// If the invalid expression happened as a result of a CompositeInsert
// overwrite, we must block this from happening next iteration.
if (composite_insert_overwritten.count(id))
block_composite_insert_overwrite.insert(id);
}
// Converts the format of the current expression from packed to unpacked,
@ -7100,7 +7107,7 @@ string CompilerGLSL::to_function_name(const TextureFunctionNameArguments &args)
// This happens for HLSL SampleCmpLevelZero on Texture2DArray and TextureCube.
bool workaround_lod_array_shadow_as_grad = false;
if (((imgtype.image.arrayed && imgtype.image.dim == Dim2D) || imgtype.image.dim == DimCube) &&
is_depth_image(imgtype, tex) && args.lod)
is_depth_image(imgtype, tex) && args.lod && !args.base.is_fetch)
{
if (!expression_is_constant_null(args.lod))
{
@ -7244,7 +7251,7 @@ string CompilerGLSL::to_function_args(const TextureFunctionArguments &args, bool
// This happens for HLSL SampleCmpLevelZero on Texture2DArray and TextureCube.
bool workaround_lod_array_shadow_as_grad =
((imgtype.image.arrayed && imgtype.image.dim == Dim2D) || imgtype.image.dim == DimCube) &&
is_depth_image(imgtype, img) && args.lod != 0;
is_depth_image(imgtype, img) && args.lod != 0 && !args.base.is_fetch;
if (args.dref)
{
@ -10309,7 +10316,9 @@ CompilerGLSL::Options::Precision CompilerGLSL::analyze_expression_precision(cons
for (uint32_t i = 0; i < length; i++)
{
uint32_t arg = args[i];
if (ir.ids[arg].get_type() == TypeConstant)
auto handle_type = ir.ids[arg].get_type();
if (handle_type == TypeConstant || handle_type == TypeConstantOp || handle_type == TypeUndef)
continue;
if (has_decoration(arg, DecorationRelaxedPrecision))
@ -11105,11 +11114,61 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
flush_variable_declaration(composite);
// Make a copy, then use access chain to store the variable.
statement(declare_temporary(result_type, id), to_expression(composite), ";");
set<SPIRExpression>(id, to_name(id), result_type, true);
auto chain = access_chain_internal(id, elems, length, ACCESS_CHAIN_INDEX_IS_LITERAL_BIT, nullptr);
statement(chain, " = ", to_unpacked_expression(obj), ";");
// CompositeInsert requires a copy + modification, but this is very awkward code in HLL.
// Speculate that the input composite is no longer used, and we can modify it in-place.
// There are various scenarios where this is not possible to satisfy.
bool can_modify_in_place = true;
forced_temporaries.insert(id);
// Cannot safely RMW PHI variables since they have no way to be invalidated,
// forcing temporaries is not going to help.
// This is similar for Constant and Undef inputs.
// The only safe thing to RMW is SPIRExpression.
if (invalid_expressions.count(composite) ||
block_composite_insert_overwrite.count(composite) ||
maybe_get<SPIRExpression>(composite) == nullptr)
{
can_modify_in_place = false;
}
else if (backend.requires_relaxed_precision_analysis &&
has_decoration(composite, DecorationRelaxedPrecision) !=
has_decoration(id, DecorationRelaxedPrecision) &&
get<SPIRType>(result_type).basetype != SPIRType::Struct)
{
// Similarly, if precision does not match for input and output,
// we cannot alias them. If we write a composite into a relaxed precision
// ID, we might get a false truncation.
can_modify_in_place = false;
}
if (can_modify_in_place)
{
// Have to make sure the modified SSA value is bound to a temporary so we can modify it in-place.
if (!forced_temporaries.count(composite))
force_temporary_and_recompile(composite);
auto chain = access_chain_internal(composite, elems, length, ACCESS_CHAIN_INDEX_IS_LITERAL_BIT, nullptr);
statement(chain, " = ", to_unpacked_expression(obj), ";");
set<SPIRExpression>(id, to_expression(composite), result_type, true);
invalid_expressions.insert(composite);
composite_insert_overwritten.insert(composite);
}
else
{
if (maybe_get<SPIRUndef>(composite) != nullptr)
{
emit_uninitialized_temporary_expression(result_type, id);
}
else
{
// Make a copy, then use access chain to store the variable.
statement(declare_temporary(result_type, id), to_expression(composite), ";");
set<SPIRExpression>(id, to_name(id), result_type, true);
}
auto chain = access_chain_internal(id, elems, length, ACCESS_CHAIN_INDEX_IS_LITERAL_BIT, nullptr);
statement(chain, " = ", to_unpacked_expression(obj), ";");
}
break;
}
@ -15704,8 +15763,43 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
break;
case SPIRBlock::Unreachable:
{
// Avoid emitting false fallthrough, which can happen for
// if (cond) break; else discard; inside a case label.
// Discard is not always implementable as a terminator.
auto &cfg = get_cfg_for_current_function();
bool inner_dominator_is_switch = false;
ID id = block.self;
while (id)
{
auto &iter_block = get<SPIRBlock>(id);
if (iter_block.terminator == SPIRBlock::MultiSelect ||
iter_block.merge == SPIRBlock::MergeLoop)
{
ID next_block = iter_block.merge == SPIRBlock::MergeLoop ?
iter_block.merge_block : iter_block.next_block;
bool outside_construct = next_block && cfg.find_common_dominator(next_block, block.self) == next_block;
if (!outside_construct)
{
inner_dominator_is_switch = iter_block.terminator == SPIRBlock::MultiSelect;
break;
}
}
if (cfg.get_preceding_edges(id).empty())
break;
id = cfg.get_immediate_dominator(id);
}
if (inner_dominator_is_switch)
statement("break; // unreachable workaround");
emit_next_block = false;
break;
}
case SPIRBlock::IgnoreIntersection:
statement("ignoreIntersectionEXT;");

View File

@ -915,6 +915,8 @@ protected:
uint32_t consume_temporary_in_precision_context(uint32_t type_id, uint32_t id, Options::Precision precision);
std::unordered_map<uint32_t, uint32_t> temporary_to_mirror_precision_alias;
std::unordered_set<uint32_t> composite_insert_overwritten;
std::unordered_set<uint32_t> block_composite_insert_overwrite;
std::string emit_for_loop_initializers(const SPIRBlock &block);
void emit_while_loop_initializers(const SPIRBlock &block);

View File

@ -15685,9 +15685,19 @@ void CompilerMSL::cast_from_variable_load(uint32_t source_id, std::string &expr,
if (var && var->storage == StorageClassWorkgroup && expr_type.basetype == SPIRType::Boolean)
expr = join(type_to_glsl(expr_type), "(", expr, ")");
// Only interested in standalone builtin variables.
// Only interested in standalone builtin variables in the switch below.
if (!has_decoration(source_id, DecorationBuiltIn))
{
// If the backing variable does not match our expected sign, we can fix it up here.
// See ensure_correct_input_type().
if (var && var->storage == StorageClassInput)
{
auto &base_type = get<SPIRType>(var->basetype);
if (base_type.basetype != SPIRType::Struct && expr_type.basetype != base_type.basetype)
expr = join(type_to_glsl(expr_type), "(", expr, ")");
}
return;
}
auto builtin = static_cast<BuiltIn>(get_decoration(source_id, DecorationBuiltIn));
auto expected_type = expr_type.basetype;