mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-17 20:52:36 +01:00
Updated spirv-cross.
This commit is contained in:
10
3rdparty/spirv-cross/spirv_common.hpp
vendored
10
3rdparty/spirv-cross/spirv_common.hpp
vendored
@@ -578,7 +578,9 @@ struct SPIRType : IVariant
|
||||
// Keep internal types at the end.
|
||||
ControlPointArray,
|
||||
Interpolant,
|
||||
Char
|
||||
Char,
|
||||
// MSL specific type, that is used by 'object'(analog of 'task' from glsl) shader.
|
||||
MeshGridProperties
|
||||
};
|
||||
|
||||
// Scalar/vector/matrix support.
|
||||
@@ -746,6 +748,10 @@ struct SPIRExpression : IVariant
|
||||
// A list of expressions which this expression depends on.
|
||||
SmallVector<ID> expression_dependencies;
|
||||
|
||||
// Similar as expression dependencies, but does not stop the tracking for force-temporary variables.
|
||||
// We need to know the full chain from store back to any SSA variable.
|
||||
SmallVector<ID> invariance_dependencies;
|
||||
|
||||
// By reading this expression, we implicitly read these expressions as well.
|
||||
// Used by access chain Store and Load since we read multiple expressions in this case.
|
||||
SmallVector<ID> implied_read_expressions;
|
||||
@@ -1598,6 +1604,8 @@ struct AccessChainMeta
|
||||
bool flattened_struct = false;
|
||||
bool relaxed_precision = false;
|
||||
bool access_meshlet_position_y = false;
|
||||
bool chain_is_builtin = false;
|
||||
spv::BuiltIn builtin = {};
|
||||
};
|
||||
|
||||
enum ExtendedDecorations
|
||||
|
||||
11
3rdparty/spirv-cross/spirv_cross.cpp
vendored
11
3rdparty/spirv-cross/spirv_cross.cpp
vendored
@@ -2569,6 +2569,15 @@ void Compiler::add_active_interface_variable(uint32_t var_id)
|
||||
|
||||
void Compiler::inherit_expression_dependencies(uint32_t dst, uint32_t source_expression)
|
||||
{
|
||||
auto *ptr_e = maybe_get<SPIRExpression>(dst);
|
||||
|
||||
if (is_position_invariant() && ptr_e && maybe_get<SPIRExpression>(source_expression))
|
||||
{
|
||||
auto &deps = ptr_e->invariance_dependencies;
|
||||
if (std::find(deps.begin(), deps.end(), source_expression) == deps.end())
|
||||
deps.push_back(source_expression);
|
||||
}
|
||||
|
||||
// Don't inherit any expression dependencies if the expression in dst
|
||||
// is not a forwarded temporary.
|
||||
if (forwarded_temporaries.find(dst) == end(forwarded_temporaries) ||
|
||||
@@ -2577,7 +2586,7 @@ void Compiler::inherit_expression_dependencies(uint32_t dst, uint32_t source_exp
|
||||
return;
|
||||
}
|
||||
|
||||
auto &e = get<SPIRExpression>(dst);
|
||||
auto &e = *ptr_e;
|
||||
auto *phi = maybe_get<SPIRVariable>(source_expression);
|
||||
if (phi && phi->phi_variable)
|
||||
{
|
||||
|
||||
@@ -928,6 +928,8 @@ void ParsedIR::reset_all_of_type(Types type)
|
||||
|
||||
void ParsedIR::add_typed_id(Types type, ID id)
|
||||
{
|
||||
assert(id < ids.size());
|
||||
|
||||
if (loop_iteration_depth_hard != 0)
|
||||
SPIRV_CROSS_THROW("Cannot add typed ID while looping over it.");
|
||||
|
||||
@@ -1030,6 +1032,8 @@ ParsedIR::LoopLock &ParsedIR::LoopLock::operator=(LoopLock &&other) SPIRV_CROSS_
|
||||
|
||||
void ParsedIR::make_constant_null(uint32_t id, uint32_t type, bool add_to_typed_id_set)
|
||||
{
|
||||
assert(id < ids.size());
|
||||
|
||||
auto &constant_type = get<SPIRType>(type);
|
||||
|
||||
if (constant_type.pointer)
|
||||
|
||||
56
3rdparty/spirv-cross/spirv_glsl.cpp
vendored
56
3rdparty/spirv-cross/spirv_glsl.cpp
vendored
@@ -6438,7 +6438,7 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
|
||||
if (splat)
|
||||
{
|
||||
res += convert_to_string(c.scalar(vector, 0));
|
||||
if (is_legacy())
|
||||
if (is_legacy() && !has_extension("GL_EXT_gpu_shader4"))
|
||||
{
|
||||
// Fake unsigned constant literals with signed ones if possible.
|
||||
// Things like array sizes, etc, tend to be unsigned even though they could just as easily be signed.
|
||||
@@ -6457,7 +6457,7 @@ string CompilerGLSL::constant_expression_vector(const SPIRConstant &c, uint32_t
|
||||
else
|
||||
{
|
||||
res += convert_to_string(c.scalar(vector, i));
|
||||
if (is_legacy())
|
||||
if (is_legacy() && !has_extension("GL_EXT_gpu_shader4"))
|
||||
{
|
||||
// Fake unsigned constant literals with signed ones if possible.
|
||||
// Things like array sizes, etc, tend to be unsigned even though they could just as easily be signed.
|
||||
@@ -10210,6 +10210,8 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice
|
||||
bool pending_array_enclose = false;
|
||||
bool dimension_flatten = false;
|
||||
bool access_meshlet_position_y = false;
|
||||
bool chain_is_builtin = false;
|
||||
spv::BuiltIn chained_builtin = {};
|
||||
|
||||
if (auto *base_expr = maybe_get<SPIRExpression>(base))
|
||||
{
|
||||
@@ -10367,6 +10369,9 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice
|
||||
auto builtin = ir.meta[base].decoration.builtin_type;
|
||||
bool mesh_shader = get_execution_model() == ExecutionModelMeshEXT;
|
||||
|
||||
chain_is_builtin = true;
|
||||
chained_builtin = builtin;
|
||||
|
||||
switch (builtin)
|
||||
{
|
||||
case BuiltInCullDistance:
|
||||
@@ -10502,6 +10507,9 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice
|
||||
{
|
||||
access_meshlet_position_y = true;
|
||||
}
|
||||
|
||||
chain_is_builtin = true;
|
||||
chained_builtin = builtin;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -10721,6 +10729,8 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice
|
||||
meta->storage_physical_type = physical_type;
|
||||
meta->relaxed_precision = relaxed_precision;
|
||||
meta->access_meshlet_position_y = access_meshlet_position_y;
|
||||
meta->chain_is_builtin = chain_is_builtin;
|
||||
meta->builtin = chained_builtin;
|
||||
}
|
||||
|
||||
return expr;
|
||||
@@ -11766,13 +11776,13 @@ void CompilerGLSL::disallow_forwarding_in_expression_chain(const SPIRExpression
|
||||
// Allow trivially forwarded expressions like OpLoad or trivial shuffles,
|
||||
// these will be marked as having suppressed usage tracking.
|
||||
// Our only concern is to make sure arithmetic operations are done in similar ways.
|
||||
if (expression_is_forwarded(expr.self) && !expression_suppresses_usage_tracking(expr.self) &&
|
||||
forced_invariant_temporaries.count(expr.self) == 0)
|
||||
if (forced_invariant_temporaries.count(expr.self) == 0)
|
||||
{
|
||||
force_temporary_and_recompile(expr.self);
|
||||
if (!expression_suppresses_usage_tracking(expr.self))
|
||||
force_temporary_and_recompile(expr.self);
|
||||
forced_invariant_temporaries.insert(expr.self);
|
||||
|
||||
for (auto &dependent : expr.expression_dependencies)
|
||||
for (auto &dependent : expr.invariance_dependencies)
|
||||
disallow_forwarding_in_expression_chain(get<SPIRExpression>(dependent));
|
||||
}
|
||||
}
|
||||
@@ -12336,6 +12346,8 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
||||
flattened_structs[ops[1]] = true;
|
||||
if (meta.relaxed_precision && backend.requires_relaxed_precision_analysis)
|
||||
set_decoration(ops[1], DecorationRelaxedPrecision);
|
||||
if (meta.chain_is_builtin)
|
||||
set_decoration(ops[1], DecorationBuiltIn, meta.builtin);
|
||||
|
||||
// If we have some expression dependencies in our access chain, this access chain is technically a forwarded
|
||||
// temporary which could be subject to invalidation.
|
||||
@@ -13229,13 +13241,24 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
||||
uint32_t op0 = ops[2];
|
||||
uint32_t op1 = ops[3];
|
||||
|
||||
// Needs special handling.
|
||||
auto &out_type = get<SPIRType>(result_type);
|
||||
|
||||
bool forward = should_forward(op0) && should_forward(op1);
|
||||
auto expr = join(to_enclosed_expression(op0), " - ", to_enclosed_expression(op1), " * ", "(",
|
||||
to_enclosed_expression(op0), " / ", to_enclosed_expression(op1), ")");
|
||||
string cast_op0, cast_op1;
|
||||
auto expected_type = binary_op_bitcast_helper(cast_op0, cast_op1, int_type, op0, op1, false);
|
||||
|
||||
// Needs special handling.
|
||||
auto expr = join(cast_op0, " - ", cast_op1, " * ", "(", cast_op0, " / ", cast_op1, ")");
|
||||
|
||||
if (implicit_integer_promotion)
|
||||
{
|
||||
expr = join(type_to_glsl(get<SPIRType>(result_type)), '(', expr, ')');
|
||||
}
|
||||
else if (out_type.basetype != int_type)
|
||||
{
|
||||
expected_type.basetype = int_type;
|
||||
expr = join(bitcast_glsl_op(out_type, expected_type), '(', expr, ')');
|
||||
}
|
||||
|
||||
emit_op(result_type, result_id, expr, forward);
|
||||
inherit_expression_dependencies(result_id, op0);
|
||||
@@ -15668,7 +15691,16 @@ string CompilerGLSL::argument_decl(const SPIRFunction::Parameter &arg)
|
||||
|
||||
if (type.pointer)
|
||||
{
|
||||
if (arg.write_count && arg.read_count)
|
||||
// If we're passing around block types to function, we really mean reference in a pointer sense,
|
||||
// but DXC does not like inout for mesh blocks, so workaround that. out is technically not correct,
|
||||
// but it works in practice due to legalization. It's ... not great, but you gotta do what you gotta do.
|
||||
// GLSL will never hit this case since it's not valid.
|
||||
if (type.storage == StorageClassOutput && get_execution_model() == ExecutionModelMeshEXT &&
|
||||
has_decoration(type.self, DecorationBlock) && is_builtin_type(type) && arg.write_count)
|
||||
{
|
||||
direction = "out ";
|
||||
}
|
||||
else if (arg.write_count && arg.read_count)
|
||||
direction = "inout ";
|
||||
else if (arg.write_count)
|
||||
direction = "out ";
|
||||
@@ -15945,7 +15977,7 @@ string CompilerGLSL::image_type_glsl(const SPIRType &type, uint32_t id, bool /*m
|
||||
case DimBuffer:
|
||||
if (options.es && options.version < 320)
|
||||
require_extension_internal("GL_EXT_texture_buffer");
|
||||
else if (!options.es && options.version < 300)
|
||||
else if (!options.es && options.version < 140)
|
||||
require_extension_internal("GL_EXT_texture_buffer_object");
|
||||
res += "Buffer";
|
||||
break;
|
||||
@@ -16488,6 +16520,8 @@ void CompilerGLSL::emit_function(SPIRFunction &func, const Bitset &return_flags)
|
||||
{
|
||||
auto &var = get<SPIRVariable>(v);
|
||||
var.deferred_declaration = false;
|
||||
if (var.storage == StorageClassTaskPayloadWorkgroupEXT)
|
||||
continue;
|
||||
|
||||
if (variable_decl_is_remapped_storage(var, StorageClassWorkgroup))
|
||||
{
|
||||
|
||||
88
3rdparty/spirv-cross/spirv_hlsl.cpp
vendored
88
3rdparty/spirv-cross/spirv_hlsl.cpp
vendored
@@ -4775,13 +4775,13 @@ void CompilerHLSL::emit_load(const Instruction &instruction)
|
||||
{
|
||||
auto ops = stream(instruction);
|
||||
|
||||
auto *chain = maybe_get<SPIRAccessChain>(ops[2]);
|
||||
uint32_t result_type = ops[0];
|
||||
uint32_t id = ops[1];
|
||||
uint32_t ptr = ops[2];
|
||||
|
||||
auto *chain = maybe_get<SPIRAccessChain>(ptr);
|
||||
if (chain)
|
||||
{
|
||||
uint32_t result_type = ops[0];
|
||||
uint32_t id = ops[1];
|
||||
uint32_t ptr = ops[2];
|
||||
|
||||
auto &type = get<SPIRType>(result_type);
|
||||
bool composite_load = !type.array.empty() || type.basetype == SPIRType::Struct;
|
||||
|
||||
@@ -4819,7 +4819,36 @@ void CompilerHLSL::emit_load(const Instruction &instruction)
|
||||
}
|
||||
}
|
||||
else
|
||||
CompilerGLSL::emit_instruction(instruction);
|
||||
{
|
||||
// Very special case where we cannot rely on IO lowering.
|
||||
// Mesh shader clip/cull arrays ... Cursed.
|
||||
auto &res_type = get<SPIRType>(result_type);
|
||||
if (get_execution_model() == ExecutionModelMeshEXT &&
|
||||
has_decoration(ptr, DecorationBuiltIn) &&
|
||||
(get_decoration(ptr, DecorationBuiltIn) == BuiltInClipDistance ||
|
||||
get_decoration(ptr, DecorationBuiltIn) == BuiltInCullDistance) &&
|
||||
is_array(res_type) && !is_array(get<SPIRType>(res_type.parent_type)) &&
|
||||
to_array_size_literal(res_type) > 1)
|
||||
{
|
||||
track_expression_read(ptr);
|
||||
string load_expr = "{ ";
|
||||
uint32_t num_elements = to_array_size_literal(res_type);
|
||||
for (uint32_t i = 0; i < num_elements; i++)
|
||||
{
|
||||
load_expr += join(to_expression(ptr), ".", index_to_swizzle(i));
|
||||
if (i + 1 < num_elements)
|
||||
load_expr += ", ";
|
||||
}
|
||||
load_expr += " }";
|
||||
emit_op(result_type, id, load_expr, false);
|
||||
register_read(id, ptr, false);
|
||||
inherit_expression_dependencies(id, ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
CompilerGLSL::emit_instruction(instruction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerHLSL::write_access_chain_array(const SPIRAccessChain &chain, uint32_t value,
|
||||
@@ -6903,3 +6932,50 @@ bool CompilerHLSL::is_user_type_structured(uint32_t id) const
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CompilerHLSL::cast_to_variable_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type)
|
||||
{
|
||||
// Loading a full array of ClipDistance needs special consideration in mesh shaders
|
||||
// since we cannot lower them by wrapping the variables in global statics.
|
||||
// Fortunately, clip/cull is a proper vector in HLSL so we can lower with simple rvalue casts.
|
||||
if (get_execution_model() != ExecutionModelMeshEXT ||
|
||||
!has_decoration(target_id, DecorationBuiltIn) ||
|
||||
!is_array(expr_type))
|
||||
{
|
||||
CompilerGLSL::cast_to_variable_store(target_id, expr, expr_type);
|
||||
return;
|
||||
}
|
||||
|
||||
auto builtin = BuiltIn(get_decoration(target_id, DecorationBuiltIn));
|
||||
if (builtin != BuiltInClipDistance && builtin != BuiltInCullDistance)
|
||||
{
|
||||
CompilerGLSL::cast_to_variable_store(target_id, expr, expr_type);
|
||||
return;
|
||||
}
|
||||
|
||||
// Array of array means one thread is storing clip distance for all vertices. Nonsensical?
|
||||
if (is_array(get<SPIRType>(expr_type.parent_type)))
|
||||
SPIRV_CROSS_THROW("Attempting to store all mesh vertices in one go. This is not supported.");
|
||||
|
||||
uint32_t num_clip = to_array_size_literal(expr_type);
|
||||
if (num_clip > 4)
|
||||
SPIRV_CROSS_THROW("Number of clip or cull distances exceeds 4, this will not work with mesh shaders.");
|
||||
|
||||
if (num_clip == 1)
|
||||
{
|
||||
// We already emit array here.
|
||||
CompilerGLSL::cast_to_variable_store(target_id, expr, expr_type);
|
||||
return;
|
||||
}
|
||||
|
||||
auto unrolled_expr = join("float", num_clip, "(");
|
||||
for (uint32_t i = 0; i < num_clip; i++)
|
||||
{
|
||||
unrolled_expr += join(expr, "[", i, "]");
|
||||
if (i + 1 < num_clip)
|
||||
unrolled_expr += ", ";
|
||||
}
|
||||
|
||||
unrolled_expr += ")";
|
||||
expr = std::move(unrolled_expr);
|
||||
}
|
||||
|
||||
2
3rdparty/spirv-cross/spirv_hlsl.hpp
vendored
2
3rdparty/spirv-cross/spirv_hlsl.hpp
vendored
@@ -408,6 +408,8 @@ private:
|
||||
std::vector<TypeID> composite_selection_workaround_types;
|
||||
|
||||
std::string get_inner_entry_point_name() const;
|
||||
|
||||
void cast_to_variable_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type) override;
|
||||
};
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
|
||||
650
3rdparty/spirv-cross/spirv_msl.cpp
vendored
650
3rdparty/spirv-cross/spirv_msl.cpp
vendored
File diff suppressed because it is too large
Load Diff
13
3rdparty/spirv-cross/spirv_msl.hpp
vendored
13
3rdparty/spirv-cross/spirv_msl.hpp
vendored
@@ -840,6 +840,7 @@ protected:
|
||||
SPVFuncImplImageFence,
|
||||
SPVFuncImplTextureCast,
|
||||
SPVFuncImplMulExtended,
|
||||
SPVFuncImplSetMeshOutputsEXT,
|
||||
};
|
||||
|
||||
// If the underlying resource has been used for comparison then duplicate loads of that resource must be too
|
||||
@@ -868,6 +869,9 @@ protected:
|
||||
std::string type_to_glsl(const SPIRType &type, uint32_t id, bool member);
|
||||
std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override;
|
||||
void emit_block_hints(const SPIRBlock &block) override;
|
||||
void emit_mesh_entry_point();
|
||||
void emit_mesh_outputs();
|
||||
void emit_mesh_tasks(SPIRBlock &block) override;
|
||||
|
||||
// Allow Metal to use the array<T> template to make arrays a value type
|
||||
std::string type_to_array_glsl(const SPIRType &type, uint32_t variable_id) override;
|
||||
@@ -919,6 +923,7 @@ protected:
|
||||
|
||||
bool is_tesc_shader() const;
|
||||
bool is_tese_shader() const;
|
||||
bool is_mesh_shader() const;
|
||||
|
||||
void preprocess_op_codes();
|
||||
void localize_global_variables();
|
||||
@@ -933,6 +938,7 @@ protected:
|
||||
std::unordered_set<uint32_t> &processed_func_ids);
|
||||
uint32_t add_interface_block(spv::StorageClass storage, bool patch = false);
|
||||
uint32_t add_interface_block_pointer(uint32_t ib_var_id, spv::StorageClass storage);
|
||||
uint32_t add_meshlet_block(bool per_primitive);
|
||||
|
||||
struct InterfaceBlockMeta
|
||||
{
|
||||
@@ -1104,12 +1110,17 @@ protected:
|
||||
uint32_t builtin_stage_input_size_id = 0;
|
||||
uint32_t builtin_local_invocation_index_id = 0;
|
||||
uint32_t builtin_workgroup_size_id = 0;
|
||||
uint32_t builtin_mesh_primitive_indices_id = 0;
|
||||
uint32_t builtin_mesh_sizes_id = 0;
|
||||
uint32_t builtin_task_grid_id = 0;
|
||||
uint32_t builtin_frag_depth_id = 0;
|
||||
uint32_t swizzle_buffer_id = 0;
|
||||
uint32_t buffer_size_buffer_id = 0;
|
||||
uint32_t view_mask_buffer_id = 0;
|
||||
uint32_t dynamic_offsets_buffer_id = 0;
|
||||
uint32_t uint_type_id = 0;
|
||||
uint32_t shared_uint_type_id = 0;
|
||||
uint32_t meshlet_type_id = 0;
|
||||
uint32_t argument_buffer_padding_buffer_type_id = 0;
|
||||
uint32_t argument_buffer_padding_image_type_id = 0;
|
||||
uint32_t argument_buffer_padding_sampler_type_id = 0;
|
||||
@@ -1174,6 +1185,8 @@ protected:
|
||||
VariableID stage_out_ptr_var_id = 0;
|
||||
VariableID tess_level_inner_var_id = 0;
|
||||
VariableID tess_level_outer_var_id = 0;
|
||||
VariableID mesh_out_per_vertex = 0;
|
||||
VariableID mesh_out_per_primitive = 0;
|
||||
VariableID stage_out_masked_builtin_type_id = 0;
|
||||
|
||||
// Handle HLSL-style 0-based vertex/instance index.
|
||||
|
||||
Reference in New Issue
Block a user