Skip to content

Commit

Permalink
update SPIRV-Cross
Browse files Browse the repository at this point in the history
  • Loading branch information
slime73 committed Jan 8, 2024
1 parent a99d5af commit 421cfd1
Show file tree
Hide file tree
Showing 22 changed files with 9,245 additions and 2,007 deletions.
392 changes: 384 additions & 8 deletions src/libraries/spirv_cross/spirv.h

Large diffs are not rendered by default.

392 changes: 384 additions & 8 deletions src/libraries/spirv_cross/spirv.hpp

Large diffs are not rendered by default.

33 changes: 27 additions & 6 deletions src/libraries/spirv_cross/spirv_cfg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,15 +306,36 @@ bool CFG::node_terminates_control_flow_in_sub_graph(BlockID from, BlockID to) co

bool true_path_ignore = false;
bool false_path_ignore = false;
if (ignore_block_id && dom.terminator == SPIRBlock::Select)

bool merges_to_nothing = dom.merge == SPIRBlock::MergeNone ||
(dom.merge == SPIRBlock::MergeSelection && dom.next_block &&
compiler.get<SPIRBlock>(dom.next_block).terminator == SPIRBlock::Unreachable) ||
(dom.merge == SPIRBlock::MergeLoop && dom.merge_block &&
compiler.get<SPIRBlock>(dom.merge_block).terminator == SPIRBlock::Unreachable);

if (dom.self == from || merges_to_nothing)
{
auto &true_block = compiler.get<SPIRBlock>(dom.true_block);
auto &false_block = compiler.get<SPIRBlock>(dom.false_block);
auto &ignore_block = compiler.get<SPIRBlock>(ignore_block_id);
true_path_ignore = compiler.execution_is_branchless(true_block, ignore_block);
false_path_ignore = compiler.execution_is_branchless(false_block, ignore_block);
// We can only ignore inner branchy paths if there is no merge,
// i.e. no code is generated afterwards. E.g. this allows us to elide continue:
// for (;;) { if (cond) { continue; } else { break; } }.
// Codegen here in SPIR-V will be something like either no merge if one path directly breaks, or
// we merge to Unreachable.
if (ignore_block_id && dom.terminator == SPIRBlock::Select)
{
auto &true_block = compiler.get<SPIRBlock>(dom.true_block);
auto &false_block = compiler.get<SPIRBlock>(dom.false_block);
auto &ignore_block = compiler.get<SPIRBlock>(ignore_block_id);
true_path_ignore = compiler.execution_is_branchless(true_block, ignore_block);
false_path_ignore = compiler.execution_is_branchless(false_block, ignore_block);
}
}

// Cases where we allow traversal. This serves as a proxy for post-dominance in a loop body.
// TODO: Might want to do full post-dominance analysis, but it's a lot of churn for something like this ...
// - We're the merge block of a selection construct. Jump to header.
// - We're the merge block of a loop. Jump to header.
// - Direct branch. Trivial.
// - Allow cases inside a branch if the header cannot merge execution before loop exit.
if ((dom.merge == SPIRBlock::MergeSelection && dom.next_block == to) ||
(dom.merge == SPIRBlock::MergeLoop && dom.merge_block == to) ||
(dom.terminator == SPIRBlock::Direct && dom.next_block == to) ||
Expand Down
5 changes: 5 additions & 0 deletions src/libraries/spirv_cross/spirv_cfg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ class CFG
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);
Expand Down
88 changes: 77 additions & 11 deletions src/libraries/spirv_cross/spirv_common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@
#ifndef SPIRV_CROSS_COMMON_HPP
#define SPIRV_CROSS_COMMON_HPP

#ifndef SPV_ENABLE_UTILITY_CODE
#define SPV_ENABLE_UTILITY_CODE
#endif
#include "spirv.hpp"

#include "spirv_cross_containers.hpp"
#include "spirv_cross_error_handling.hpp"
#include <functional>
Expand Down Expand Up @@ -291,6 +295,20 @@ inline std::string convert_to_string(double t, char locale_radix_point)
return buf;
}

#if defined(__clang__) || defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning(pop)
#endif

class FloatFormatter
{
public:
virtual ~FloatFormatter() = default;
virtual std::string format_float(float value) = 0;
virtual std::string format_double(double value) = 0;
};

template <typename T>
struct ValueSaver
{
Expand All @@ -314,12 +332,6 @@ struct ValueSaver
T saved;
};

#if defined(__clang__) || defined(__GNUC__)
#pragma GCC diagnostic pop
#elif defined(_MSC_VER)
#pragma warning(pop)
#endif

struct Instruction
{
uint16_t op = 0;
Expand Down Expand Up @@ -536,6 +548,9 @@ struct SPIRType : IVariant
type = TypeType
};

spv::Op op = spv::Op::OpNop;
explicit SPIRType(spv::Op op_) : op(op_) {}

enum BaseType
{
Unknown,
Expand Down Expand Up @@ -606,7 +621,7 @@ struct SPIRType : IVariant
uint32_t sampled;
spv::ImageFormat format;
spv::AccessQualifier access;
} image;
} image = {};

// Structs can be declared multiple times if they are used as part of interface blocks.
// We want to detect this so that we only emit the struct definition once.
Expand Down Expand Up @@ -638,7 +653,10 @@ struct SPIRExtension : IVariant
SPV_AMD_shader_ballot,
SPV_AMD_shader_explicit_vertex_parameter,
SPV_AMD_shader_trinary_minmax,
SPV_AMD_gcn_shader
SPV_AMD_gcn_shader,
NonSemanticDebugPrintf,
NonSemanticShaderDebugInfo,
NonSemanticGeneric
};

explicit SPIRExtension(Extension ext_)
Expand Down Expand Up @@ -672,10 +690,12 @@ struct SPIREntryPoint
struct WorkgroupSize
{
uint32_t x = 0, y = 0, z = 0;
uint32_t id_x = 0, id_y = 0, id_z = 0;
uint32_t constant = 0; // Workgroup size can be expressed as a constant/spec-constant instead.
} workgroup_size;
uint32_t invocations = 0;
uint32_t output_vertices = 0;
uint32_t output_primitives = 0;
spv::ExecutionModel model = spv::ExecutionModelMax;
bool geometry_passthrough = false;
};
Expand All @@ -689,7 +709,7 @@ struct SPIRExpression : IVariant

// Only created by the backend target to avoid creating tons of temporaries.
SPIRExpression(std::string expr, TypeID expression_type_, bool immutable_)
: expression(move(expr))
: expression(std::move(expr))
, expression_type(expression_type_)
, immutable(immutable_)
{
Expand Down Expand Up @@ -720,6 +740,9 @@ struct SPIRExpression : IVariant
// Whether or not this is an access chain expression.
bool access_chain = false;

// Whether or not gl_MeshVerticesEXT[].gl_Position (as a whole or .y) is referenced
bool access_meshlet_position_y = false;

// A list of expressions which this expression depends on.
SmallVector<ID> expression_dependencies;

Expand Down Expand Up @@ -770,7 +793,8 @@ struct SPIRBlock : IVariant
Unreachable, // Noop
Kill, // Discard
IgnoreIntersection, // Ray Tracing
TerminateRay // Ray Tracing
TerminateRay, // Ray Tracing
EmitMeshTasks // Mesh shaders
};

enum Merge
Expand Down Expand Up @@ -832,6 +856,13 @@ struct SPIRBlock : IVariant
BlockID false_block = 0;
BlockID default_block = 0;

// If terminator is EmitMeshTasksEXT.
struct
{
ID groups[3];
ID payload;
} mesh = {};

SmallVector<Instruction> ops;

struct Phi
Expand Down Expand Up @@ -1071,7 +1102,6 @@ struct SPIRVariable : IVariant

// Temporaries which can remain forwarded as long as this variable is not modified.
SmallVector<ID> dependees;
bool forwardable = true;

bool deferred_declaration = false;
bool phi_variable = false;
Expand Down Expand Up @@ -1563,6 +1593,8 @@ struct AccessChainMeta
bool storage_is_packed = false;
bool storage_is_invariant = false;
bool flattened_struct = false;
bool relaxed_precision = false;
bool access_meshlet_position_y = false;
};

enum ExtendedDecorations
Expand Down Expand Up @@ -1630,6 +1662,12 @@ enum ExtendedDecorations
// results of interpolation can.
SPIRVCrossDecorationInterpolantComponentExpr,

// Apply to any struct type that is used in the Workgroup storage class.
// This causes matrices in MSL prior to Metal 3.0 to be emitted using a special
// class that is convertible to the standard matrix type, to work around the
// lack of constructors in the 'threadgroup' address space.
SPIRVCrossDecorationWorkgroupStruct,

SPIRVCrossDecorationCount
};

Expand All @@ -1640,6 +1678,7 @@ struct Meta
std::string alias;
std::string qualified_alias;
std::string hlsl_semantic;
std::string user_type;
Bitset decoration_flags;
spv::BuiltIn builtin_type = spv::BuiltInMax;
uint32_t location = 0;
Expand Down Expand Up @@ -1775,6 +1814,33 @@ static inline bool opcode_is_sign_invariant(spv::Op opcode)
}
}

static inline bool opcode_can_promote_integer_implicitly(spv::Op opcode)
{
switch (opcode)
{
case spv::OpSNegate:
case spv::OpNot:
case spv::OpBitwiseAnd:
case spv::OpBitwiseOr:
case spv::OpBitwiseXor:
case spv::OpShiftLeftLogical:
case spv::OpShiftRightLogical:
case spv::OpShiftRightArithmetic:
case spv::OpIAdd:
case spv::OpISub:
case spv::OpIMul:
case spv::OpSDiv:
case spv::OpUDiv:
case spv::OpSRem:
case spv::OpUMod:
case spv::OpSMod:
return true;

default:
return false;
}
}

struct SetBindingPair
{
uint32_t desc_set;
Expand Down
7 changes: 1 addition & 6 deletions src/libraries/spirv_cross/spirv_cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,6 @@ void CompilerCPP::emit_resources()
if (emitted)
statement("");

declare_undefined_values();

statement("inline void init(spirv_cross_shader& s)");
begin_scope();
statement(resource_type, "::init(s);");
Expand Down Expand Up @@ -338,11 +336,8 @@ string CompilerCPP::compile()
uint32_t pass_count = 0;
do
{
if (pass_count >= 3)
SPIRV_CROSS_THROW("Over 3 compilation loops detected. Must be a bug!");

resource_registrations.clear();
reset();
reset(pass_count);

// Move constructor for this type is broken on GCC 4.9 ...
buffer.reset();
Expand Down
Loading

0 comments on commit 421cfd1

Please sign in to comment.