Replace spirv-cross with spirv-reflect (#186)

This commit is contained in:
Turánszki János
2020-11-10 23:58:51 +01:00
committed by GitHub
parent f970b72ce0
commit abacc054c8
37 changed files with 7791 additions and 55583 deletions
+3
View File
@@ -10,3 +10,6 @@ insert_final_newline = true
# space, tab
indent_style = tab
indent_size = 4
[*.py]
indent_style = space
+2 -12
View File
@@ -1,15 +1,5 @@
add_library(Utility STATIC
D3D12MemAlloc.cpp
spirv_cfg.cpp
spirv_cpp.cpp
spirv_cross.cpp
spirv_cross_c.cpp
spirv_cross_parsed_ir.cpp
spirv_cross_util.cpp
spirv_glsl.cpp
spirv_hlsl.cpp
spirv_msl.cpp
spirv_parser.cpp
spirv_reflect.cpp
utility_common.cpp
)
spirv_reflect.c
)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-397
View File
@@ -1,397 +0,0 @@
/*
* Copyright 2016-2020 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "spirv_cfg.hpp"
#include "spirv_cross.hpp"
#include <algorithm>
#include <assert.h>
using namespace std;
namespace SPIRV_CROSS_NAMESPACE
{
CFG::CFG(Compiler &compiler_, const SPIRFunction &func_)
: compiler(compiler_)
, func(func_)
{
build_post_order_visit_order();
build_immediate_dominators();
}
uint32_t CFG::find_common_dominator(uint32_t a, uint32_t b) const
{
while (a != b)
{
if (get_visit_order(a) < get_visit_order(b))
a = get_immediate_dominator(a);
else
b = get_immediate_dominator(b);
}
return a;
}
void CFG::build_immediate_dominators()
{
// Traverse the post-order in reverse and build up the immediate dominator tree.
immediate_dominators.clear();
immediate_dominators[func.entry_block] = func.entry_block;
for (auto i = post_order.size(); i; i--)
{
uint32_t block = post_order[i - 1];
auto &pred = preceding_edges[block];
if (pred.empty()) // This is for the entry block, but we've already set up the dominators.
continue;
for (auto &edge : pred)
{
if (immediate_dominators[block])
{
assert(immediate_dominators[edge]);
immediate_dominators[block] = find_common_dominator(immediate_dominators[block], edge);
}
else
immediate_dominators[block] = edge;
}
}
}
bool CFG::is_back_edge(uint32_t to) const
{
// We have a back edge if the visit order is set with the temporary magic value 0.
// Crossing edges will have already been recorded with a visit order.
auto itr = visit_order.find(to);
return itr != end(visit_order) && itr->second.get() == 0;
}
bool CFG::has_visited_forward_edge(uint32_t to) const
{
// If > 0, we have visited the edge already, and this is not a back edge branch.
auto itr = visit_order.find(to);
return itr != end(visit_order) && itr->second.get() > 0;
}
bool CFG::post_order_visit(uint32_t block_id)
{
// If we have already branched to this block (back edge), stop recursion.
// If our branches are back-edges, we do not record them.
// We have to record crossing edges however.
if (has_visited_forward_edge(block_id))
return true;
else if (is_back_edge(block_id))
return false;
// Block back-edges from recursively revisiting ourselves.
visit_order[block_id].get() = 0;
auto &block = compiler.get<SPIRBlock>(block_id);
// If this is a loop header, add an implied branch to the merge target.
// This is needed to avoid annoying cases with do { ... } while(false) loops often generated by inliners.
// To the CFG, this is linear control flow, but we risk picking the do/while scope as our dominating block.
// This makes sure that if we are accessing a variable outside the do/while, we choose the loop header as dominator.
// We could use has_visited_forward_edge, but this break code-gen where the merge block is unreachable in the CFG.
// Make a point out of visiting merge target first. This is to make sure that post visit order outside the loop
// is lower than inside the loop, which is going to be key for some traversal algorithms like post-dominance analysis.
// For selection constructs true/false blocks will end up visiting the merge block directly and it works out fine,
// but for loops, only the header might end up actually branching to merge block.
if (block.merge == SPIRBlock::MergeLoop && post_order_visit(block.merge_block))
add_branch(block_id, block.merge_block);
// First visit our branch targets.
switch (block.terminator)
{
case SPIRBlock::Direct:
if (post_order_visit(block.next_block))
add_branch(block_id, block.next_block);
break;
case SPIRBlock::Select:
if (post_order_visit(block.true_block))
add_branch(block_id, block.true_block);
if (post_order_visit(block.false_block))
add_branch(block_id, block.false_block);
break;
case SPIRBlock::MultiSelect:
for (auto &target : block.cases)
{
if (post_order_visit(target.block))
add_branch(block_id, target.block);
}
if (block.default_block && post_order_visit(block.default_block))
add_branch(block_id, block.default_block);
break;
default:
break;
}
// If this is a selection merge, add an implied branch to the merge target.
// This is needed to avoid cases where an inner branch dominates the outer branch.
// This can happen if one of the branches exit early, e.g.:
// if (cond) { ...; break; } else { var = 100 } use_var(var);
// We can use the variable without a Phi since there is only one possible parent here.
// However, in this case, we need to hoist out the inner variable to outside the branch.
// Use same strategy as loops.
if (block.merge == SPIRBlock::MergeSelection && post_order_visit(block.next_block))
{
// If there is only one preceding edge to the merge block and it's not ourselves, we need a fixup.
// Add a fake branch so any dominator in either the if (), or else () block, or a lone case statement
// will be hoisted out to outside the selection merge.
// If size > 1, the variable will be automatically hoisted, so we should not mess with it.
// The exception here is switch blocks, where we can have multiple edges to merge block,
// all coming from same scope, so be more conservative in this case.
// Adding fake branches unconditionally breaks parameter preservation analysis,
// which looks at how variables are accessed through the CFG.
auto pred_itr = preceding_edges.find(block.next_block);
if (pred_itr != end(preceding_edges))
{
auto &pred = pred_itr->second;
auto succ_itr = succeeding_edges.find(block_id);
size_t num_succeeding_edges = 0;
if (succ_itr != end(succeeding_edges))
num_succeeding_edges = succ_itr->second.size();
if (block.terminator == SPIRBlock::MultiSelect && num_succeeding_edges == 1)
{
// Multiple branches can come from the same scope due to "break;", so we need to assume that all branches
// come from same case scope in worst case, even if there are multiple preceding edges.
// If we have more than one succeeding edge from the block header, it should be impossible
// to have a dominator be inside the block.
// Only case this can go wrong is if we have 2 or more edges from block header and
// 2 or more edges to merge block, and still have dominator be inside a case label.
if (!pred.empty())
add_branch(block_id, block.next_block);
}
else
{
if (pred.size() == 1 && *pred.begin() != block_id)
add_branch(block_id, block.next_block);
}
}
else
{
// If the merge block does not have any preceding edges, i.e. unreachable, hallucinate it.
// We're going to do code-gen for it, and domination analysis requires that we have at least one preceding edge.
add_branch(block_id, block.next_block);
}
}
// Then visit ourselves. Start counting at one, to let 0 be a magic value for testing back vs. crossing edges.
visit_order[block_id].get() = ++visit_count;
post_order.push_back(block_id);
return true;
}
void CFG::build_post_order_visit_order()
{
uint32_t block = func.entry_block;
visit_count = 0;
visit_order.clear();
post_order.clear();
post_order_visit(block);
}
void CFG::add_branch(uint32_t from, uint32_t to)
{
const auto add_unique = [](SmallVector<uint32_t> &l, uint32_t value) {
auto itr = find(begin(l), end(l), value);
if (itr == end(l))
l.push_back(value);
};
add_unique(preceding_edges[to], from);
add_unique(succeeding_edges[from], to);
}
uint32_t CFG::find_loop_dominator(uint32_t block_id) const
{
while (block_id != SPIRBlock::NoDominator)
{
auto itr = preceding_edges.find(block_id);
if (itr == end(preceding_edges))
return SPIRBlock::NoDominator;
if (itr->second.empty())
return SPIRBlock::NoDominator;
uint32_t pred_block_id = SPIRBlock::NoDominator;
bool ignore_loop_header = false;
// If we are a merge block, go directly to the header block.
// Only consider a loop dominator if we are branching from inside a block to a loop header.
// NOTE: In the CFG we forced an edge from header to merge block always to support variable scopes properly.
for (auto &pred : itr->second)
{
auto &pred_block = compiler.get<SPIRBlock>(pred);
if (pred_block.merge == SPIRBlock::MergeLoop && pred_block.merge_block == ID(block_id))
{
pred_block_id = pred;
ignore_loop_header = true;
break;
}
else if (pred_block.merge == SPIRBlock::MergeSelection && pred_block.next_block == ID(block_id))
{
pred_block_id = pred;
break;
}
}
// No merge block means we can just pick any edge. Loop headers dominate the inner loop, so any path we
// take will lead there.
if (pred_block_id == SPIRBlock::NoDominator)
pred_block_id = itr->second.front();
block_id = pred_block_id;
if (!ignore_loop_header && block_id)
{
auto &block = compiler.get<SPIRBlock>(block_id);
if (block.merge == SPIRBlock::MergeLoop)
return block_id;
}
}
return block_id;
}
bool CFG::node_terminates_control_flow_in_sub_graph(BlockID from, BlockID to) const
{
// Walk backwards, starting from "to" block.
// Only follow pred edges if they have a 1:1 relationship, or a merge relationship.
// If we cannot find a path to "from", we must assume that to is inside control flow in some way.
auto &from_block = compiler.get<SPIRBlock>(from);
BlockID ignore_block_id = 0;
if (from_block.merge == SPIRBlock::MergeLoop)
ignore_block_id = from_block.merge_block;
while (to != from)
{
auto pred_itr = preceding_edges.find(to);
if (pred_itr == end(preceding_edges))
return false;
DominatorBuilder builder(*this);
for (auto &edge : pred_itr->second)
builder.add_block(edge);
uint32_t dominator = builder.get_dominator();
if (dominator == 0)
return false;
auto &dom = compiler.get<SPIRBlock>(dominator);
bool true_path_ignore = false;
bool false_path_ignore = false;
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);
}
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) ||
(dom.terminator == SPIRBlock::Select && dom.true_block == to && false_path_ignore) ||
(dom.terminator == SPIRBlock::Select && dom.false_block == to && true_path_ignore))
{
// Allow walking selection constructs if the other branch reaches out of a loop construct.
// It cannot be in-scope anymore.
to = dominator;
}
else
return false;
}
return true;
}
DominatorBuilder::DominatorBuilder(const CFG &cfg_)
: cfg(cfg_)
{
}
void DominatorBuilder::add_block(uint32_t block)
{
if (!cfg.get_immediate_dominator(block))
{
// Unreachable block via the CFG, we will never emit this code anyways.
return;
}
if (!dominator)
{
dominator = block;
return;
}
if (block != dominator)
dominator = cfg.find_common_dominator(block, dominator);
}
void DominatorBuilder::lift_continue_block_dominator()
{
// It is possible for a continue block to be the dominator of a variable is only accessed inside the while block of a do-while loop.
// We cannot safely declare variables inside a continue block, so move any variable declared
// in a continue block to the entry block to simplify.
// It makes very little sense for a continue block to ever be a dominator, so fall back to the simplest
// solution.
if (!dominator)
return;
auto &block = cfg.get_compiler().get<SPIRBlock>(dominator);
auto post_order = cfg.get_visit_order(dominator);
// If we are branching to a block with a higher post-order traversal index (continue blocks), we have a problem
// since we cannot create sensible GLSL code for this, fallback to entry block.
bool back_edge_dominator = false;
switch (block.terminator)
{
case SPIRBlock::Direct:
if (cfg.get_visit_order(block.next_block) > post_order)
back_edge_dominator = true;
break;
case SPIRBlock::Select:
if (cfg.get_visit_order(block.true_block) > post_order)
back_edge_dominator = true;
if (cfg.get_visit_order(block.false_block) > post_order)
back_edge_dominator = true;
break;
case SPIRBlock::MultiSelect:
for (auto &target : block.cases)
{
if (cfg.get_visit_order(target.block) > post_order)
back_edge_dominator = true;
}
if (block.default_block && cfg.get_visit_order(block.default_block) > post_order)
back_edge_dominator = true;
break;
default:
break;
}
if (back_edge_dominator)
dominator = cfg.get_function().entry_block;
}
} // namespace SPIRV_CROSS_NAMESPACE
-156
View File
@@ -1,156 +0,0 @@
/*
* Copyright 2016-2020 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SPIRV_CROSS_CFG_HPP
#define SPIRV_CROSS_CFG_HPP
#include "spirv_common.hpp"
#include <assert.h>
namespace SPIRV_CROSS_NAMESPACE
{
class Compiler;
class CFG
{
public:
CFG(Compiler &compiler, const SPIRFunction &function);
Compiler &get_compiler()
{
return compiler;
}
const Compiler &get_compiler() const
{
return compiler;
}
const SPIRFunction &get_function() const
{
return func;
}
uint32_t get_immediate_dominator(uint32_t block) const
{
auto itr = immediate_dominators.find(block);
if (itr != std::end(immediate_dominators))
return itr->second;
else
return 0;
}
uint32_t get_visit_order(uint32_t block) const
{
auto itr = visit_order.find(block);
assert(itr != std::end(visit_order));
int v = itr->second.get();
assert(v > 0);
return uint32_t(v);
}
uint32_t find_common_dominator(uint32_t a, uint32_t b) const;
const SmallVector<uint32_t> &get_preceding_edges(uint32_t block) const
{
auto itr = preceding_edges.find(block);
if (itr != std::end(preceding_edges))
return itr->second;
else
return empty_vector;
}
const SmallVector<uint32_t> &get_succeeding_edges(uint32_t block) const
{
auto itr = succeeding_edges.find(block);
if (itr != std::end(succeeding_edges))
return itr->second;
else
return empty_vector;
}
template <typename Op>
void walk_from(std::unordered_set<uint32_t> &seen_blocks, uint32_t block, const Op &op) const
{
if (seen_blocks.count(block))
return;
seen_blocks.insert(block);
if (op(block))
{
for (auto b : get_succeeding_edges(block))
walk_from(seen_blocks, b, op);
}
}
uint32_t find_loop_dominator(uint32_t block) const;
bool node_terminates_control_flow_in_sub_graph(BlockID from, BlockID to) const;
private:
struct VisitOrder
{
int &get()
{
return v;
}
const int &get() const
{
return v;
}
int v = -1;
};
Compiler &compiler;
const SPIRFunction &func;
std::unordered_map<uint32_t, SmallVector<uint32_t>> preceding_edges;
std::unordered_map<uint32_t, SmallVector<uint32_t>> succeeding_edges;
std::unordered_map<uint32_t, uint32_t> immediate_dominators;
std::unordered_map<uint32_t, VisitOrder> visit_order;
SmallVector<uint32_t> post_order;
SmallVector<uint32_t> empty_vector;
void add_branch(uint32_t from, uint32_t to);
void build_post_order_visit_order();
void build_immediate_dominators();
bool post_order_visit(uint32_t block);
uint32_t visit_count = 0;
bool is_back_edge(uint32_t to) const;
bool has_visited_forward_edge(uint32_t to) const;
};
class DominatorBuilder
{
public:
DominatorBuilder(const CFG &cfg);
void add_block(uint32_t block);
uint32_t get_dominator() const
{
return dominator;
}
void lift_continue_block_dominator();
private:
const CFG &cfg;
uint32_t dominator = 0;
};
} // namespace SPIRV_CROSS_NAMESPACE
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-86
View File
@@ -1,86 +0,0 @@
/*
* Copyright 2015-2020 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SPIRV_CROSS_CPP_HPP
#define SPIRV_CROSS_CPP_HPP
#include "spirv_glsl.hpp"
#include <utility>
namespace SPIRV_CROSS_NAMESPACE
{
class CompilerCPP : public CompilerGLSL
{
public:
explicit CompilerCPP(std::vector<uint32_t> spirv_)
: CompilerGLSL(std::move(spirv_))
{
}
CompilerCPP(const uint32_t *ir_, size_t word_count)
: CompilerGLSL(ir_, word_count)
{
}
explicit CompilerCPP(const ParsedIR &ir_)
: CompilerGLSL(ir_)
{
}
explicit CompilerCPP(ParsedIR &&ir_)
: CompilerGLSL(std::move(ir_))
{
}
std::string compile() override;
// Sets a custom symbol name that can override
// spirv_cross_get_interface.
//
// Useful when several shader interfaces are linked
// statically into the same binary.
void set_interface_name(std::string name)
{
interface_name = std::move(name);
}
private:
void emit_header() override;
void emit_c_linkage();
void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) override;
void emit_resources();
void emit_buffer_block(const SPIRVariable &type) override;
void emit_push_constant_block(const SPIRVariable &var) override;
void emit_interface_block(const SPIRVariable &type);
void emit_block_chain(SPIRBlock &block);
void emit_uniform(const SPIRVariable &var) override;
void emit_shared(const SPIRVariable &var);
void emit_block_struct(SPIRType &type);
std::string variable_decl(const SPIRType &type, const std::string &name, uint32_t id) override;
std::string argument_decl(const SPIRFunction::Parameter &arg);
SmallVector<std::string> resource_registrations;
std::string impl_type;
std::string resource_type;
uint32_t shared_counter = 0;
std::string interface_name;
};
} // namespace SPIRV_CROSS_NAMESPACE
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,87 +0,0 @@
/*
* Copyright 2015-2020 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SPIRV_CROSS_ERROR_HANDLING
#define SPIRV_CROSS_ERROR_HANDLING
#include <stdio.h>
#include <stdlib.h>
#include <string>
#ifndef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
#include <stdexcept>
#endif
#ifdef SPIRV_CROSS_NAMESPACE_OVERRIDE
#define SPIRV_CROSS_NAMESPACE SPIRV_CROSS_NAMESPACE_OVERRIDE
#else
#define SPIRV_CROSS_NAMESPACE spirv_cross
#endif
namespace SPIRV_CROSS_NAMESPACE
{
#ifdef SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
#if !defined(_MSC_VER) || defined(__clang__)
[[noreturn]]
#elif defined(_MSC_VER)
__declspec(noreturn)
#endif
inline void
report_and_abort(const std::string &msg)
{
#ifdef NDEBUG
(void)msg;
#else
fprintf(stderr, "There was a compiler error: %s\n", msg.c_str());
#endif
fflush(stderr);
abort();
}
#define SPIRV_CROSS_THROW(x) report_and_abort(x)
#else
class CompilerError : public std::runtime_error
{
public:
explicit CompilerError(const std::string &str)
: std::runtime_error(str)
{
}
};
#define SPIRV_CROSS_THROW(x) throw CompilerError(x)
#endif
// MSVC 2013 does not have noexcept. We need this for Variant to get move constructor to work correctly
// instead of copy constructor.
// MSVC 2013 ignores that move constructors cannot throw in std::vector, so just don't define it.
#if defined(_MSC_VER) && _MSC_VER < 1900
#define SPIRV_CROSS_NOEXCEPT
#else
#define SPIRV_CROSS_NOEXCEPT noexcept
#endif
#if __cplusplus >= 201402l
#define SPIRV_CROSS_DEPRECATED(reason) [[deprecated(reason)]]
#elif defined(__GNUC__)
#define SPIRV_CROSS_DEPRECATED(reason) __attribute__((deprecated))
#elif defined(_MSC_VER)
#define SPIRV_CROSS_DEPRECATED(reason) __declspec(deprecated(reason))
#else
#define SPIRV_CROSS_DEPRECATED(reason)
#endif
} // namespace SPIRV_CROSS_NAMESPACE
#endif
File diff suppressed because it is too large Load Diff
@@ -1,231 +0,0 @@
/*
* Copyright 2018-2020 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SPIRV_CROSS_PARSED_IR_HPP
#define SPIRV_CROSS_PARSED_IR_HPP
#include "spirv_common.hpp"
#include <stdint.h>
#include <unordered_map>
namespace SPIRV_CROSS_NAMESPACE
{
// This data structure holds all information needed to perform cross-compilation and reflection.
// It is the output of the Parser, but any implementation could create this structure.
// It is intentionally very "open" and struct-like with some helper functions to deal with decorations.
// Parser is the reference implementation of how this data structure should be filled in.
class ParsedIR
{
private:
// This must be destroyed after the "ids" vector.
std::unique_ptr<ObjectPoolGroup> pool_group;
public:
ParsedIR();
// Due to custom allocations from object pools, we cannot use a default copy constructor.
ParsedIR(const ParsedIR &other);
ParsedIR &operator=(const ParsedIR &other);
// Moves are unproblematic, but we need to implement it anyways, since MSVC 2013 does not understand
// how to default-implement these.
ParsedIR(ParsedIR &&other) SPIRV_CROSS_NOEXCEPT;
ParsedIR &operator=(ParsedIR &&other) SPIRV_CROSS_NOEXCEPT;
// Resizes ids, meta and block_meta.
void set_id_bounds(uint32_t bounds);
// The raw SPIR-V, instructions and opcodes refer to this by offset + count.
std::vector<uint32_t> spirv;
// Holds various data structures which inherit from IVariant.
SmallVector<Variant> ids;
// Various meta data for IDs, decorations, names, etc.
std::unordered_map<ID, Meta> meta;
// Holds all IDs which have a certain type.
// This is needed so we can iterate through a specific kind of resource quickly,
// and in-order of module declaration.
SmallVector<ID> ids_for_type[TypeCount];
// Special purpose lists which contain a union of types.
// This is needed so we can declare specialization constants and structs in an interleaved fashion,
// among other things.
// Constants can be of struct type, and struct array sizes can use specialization constants.
SmallVector<ID> ids_for_constant_or_type;
SmallVector<ID> ids_for_constant_or_variable;
// Declared capabilities and extensions in the SPIR-V module.
// Not really used except for reflection at the moment.
SmallVector<spv::Capability> declared_capabilities;
SmallVector<std::string> declared_extensions;
// Meta data about blocks. The cross-compiler needs to query if a block is either of these types.
// It is a bitset as there can be more than one tag per block.
enum BlockMetaFlagBits
{
BLOCK_META_LOOP_HEADER_BIT = 1 << 0,
BLOCK_META_CONTINUE_BIT = 1 << 1,
BLOCK_META_LOOP_MERGE_BIT = 1 << 2,
BLOCK_META_SELECTION_MERGE_BIT = 1 << 3,
BLOCK_META_MULTISELECT_MERGE_BIT = 1 << 4
};
using BlockMetaFlags = uint8_t;
SmallVector<BlockMetaFlags> block_meta;
std::unordered_map<BlockID, BlockID> continue_block_to_loop_header;
// Normally, we'd stick SPIREntryPoint in ids array, but it conflicts with SPIRFunction.
// Entry points can therefore be seen as some sort of meta structure.
std::unordered_map<FunctionID, SPIREntryPoint> entry_points;
FunctionID default_entry_point = 0;
struct Source
{
uint32_t version = 0;
bool es = false;
bool known = false;
bool hlsl = false;
Source() = default;
};
Source source;
spv::AddressingModel addressing_model = spv::AddressingModelMax;
spv::MemoryModel memory_model = spv::MemoryModelMax;
// Decoration handling methods.
// Can be useful for simple "raw" reflection.
// However, most members are here because the Parser needs most of these,
// and might as well just have the whole suite of decoration/name handling in one place.
void set_name(ID id, const std::string &name);
const std::string &get_name(ID id) const;
void set_decoration(ID id, spv::Decoration decoration, uint32_t argument = 0);
void set_decoration_string(ID id, spv::Decoration decoration, const std::string &argument);
bool has_decoration(ID id, spv::Decoration decoration) const;
uint32_t get_decoration(ID id, spv::Decoration decoration) const;
const std::string &get_decoration_string(ID id, spv::Decoration decoration) const;
const Bitset &get_decoration_bitset(ID id) const;
void unset_decoration(ID id, spv::Decoration decoration);
// Decoration handling methods (for members of a struct).
void set_member_name(TypeID id, uint32_t index, const std::string &name);
const std::string &get_member_name(TypeID id, uint32_t index) const;
void set_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration, uint32_t argument = 0);
void set_member_decoration_string(TypeID id, uint32_t index, spv::Decoration decoration,
const std::string &argument);
uint32_t get_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration) const;
const std::string &get_member_decoration_string(TypeID id, uint32_t index, spv::Decoration decoration) const;
bool has_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration) const;
const Bitset &get_member_decoration_bitset(TypeID id, uint32_t index) const;
void unset_member_decoration(TypeID id, uint32_t index, spv::Decoration decoration);
void mark_used_as_array_length(ID id);
uint32_t increase_bound_by(uint32_t count);
Bitset get_buffer_block_flags(const SPIRVariable &var) const;
void add_typed_id(Types type, ID id);
void remove_typed_id(Types type, ID id);
class LoopLock
{
public:
explicit LoopLock(uint32_t *counter);
LoopLock(const LoopLock &) = delete;
void operator=(const LoopLock &) = delete;
LoopLock(LoopLock &&other) SPIRV_CROSS_NOEXCEPT;
LoopLock &operator=(LoopLock &&other) SPIRV_CROSS_NOEXCEPT;
~LoopLock();
private:
uint32_t *lock;
};
// This must be held while iterating over a type ID array.
// It is undefined if someone calls set<>() while we're iterating over a data structure, so we must
// make sure that this case is avoided.
// If we have a hard lock, it is an error to call set<>(), and an exception is thrown.
// If we have a soft lock, we silently ignore any additions to the typed arrays.
// This should only be used for physical ID remapping where we need to create an ID, but we will never
// care about iterating over them.
LoopLock create_loop_hard_lock() const;
LoopLock create_loop_soft_lock() const;
template <typename T, typename Op>
void for_each_typed_id(const Op &op)
{
auto loop_lock = create_loop_hard_lock();
for (auto &id : ids_for_type[T::type])
{
if (ids[id].get_type() == static_cast<Types>(T::type))
op(id, get<T>(id));
}
}
template <typename T, typename Op>
void for_each_typed_id(const Op &op) const
{
auto loop_lock = create_loop_hard_lock();
for (auto &id : ids_for_type[T::type])
{
if (ids[id].get_type() == static_cast<Types>(T::type))
op(id, get<T>(id));
}
}
template <typename T>
void reset_all_of_type()
{
reset_all_of_type(static_cast<Types>(T::type));
}
void reset_all_of_type(Types type);
Meta *find_meta(ID id);
const Meta *find_meta(ID id) const;
const std::string &get_empty_string() const
{
return empty_string;
}
void make_constant_null(uint32_t id, uint32_t type, bool add_to_typed_id_set);
private:
template <typename T>
T &get(uint32_t id)
{
return variant_get<T>(ids[id]);
}
template <typename T>
const T &get(uint32_t id) const
{
return variant_get<T>(ids[id]);
}
mutable uint32_t loop_iteration_depth_hard = 0;
mutable uint32_t loop_iteration_depth_soft = 0;
std::string empty_string;
Bitset cleared_bitset;
};
} // namespace SPIRV_CROSS_NAMESPACE
#endif
-70
View File
@@ -1,70 +0,0 @@
/*
* Copyright 2015-2020 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "spirv_cross_util.hpp"
#include "spirv_common.hpp"
using namespace spv;
using namespace SPIRV_CROSS_NAMESPACE;
namespace spirv_cross_util
{
void rename_interface_variable(Compiler &compiler, const SmallVector<Resource> &resources, uint32_t location,
const std::string &name)
{
for (auto &v : resources)
{
if (!compiler.has_decoration(v.id, spv::DecorationLocation))
continue;
auto loc = compiler.get_decoration(v.id, spv::DecorationLocation);
if (loc != location)
continue;
auto &type = compiler.get_type(v.base_type_id);
// This is more of a friendly variant. If we need to rename interface variables, we might have to rename
// structs as well and make sure all the names match up.
if (type.basetype == SPIRType::Struct)
{
compiler.set_name(v.base_type_id, join("SPIRV_Cross_Interface_Location", location));
for (uint32_t i = 0; i < uint32_t(type.member_types.size()); i++)
compiler.set_member_name(v.base_type_id, i, join("InterfaceMember", i));
}
compiler.set_name(v.id, name);
}
}
void inherit_combined_sampler_bindings(Compiler &compiler)
{
auto &samplers = compiler.get_combined_image_samplers();
for (auto &s : samplers)
{
if (compiler.has_decoration(s.image_id, spv::DecorationDescriptorSet))
{
uint32_t set = compiler.get_decoration(s.image_id, spv::DecorationDescriptorSet);
compiler.set_decoration(s.combined_id, spv::DecorationDescriptorSet, set);
}
if (compiler.has_decoration(s.image_id, spv::DecorationBinding))
{
uint32_t binding = compiler.get_decoration(s.image_id, spv::DecorationBinding);
compiler.set_decoration(s.combined_id, spv::DecorationBinding, binding);
}
}
}
} // namespace spirv_cross_util
-30
View File
@@ -1,30 +0,0 @@
/*
* Copyright 2015-2020 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SPIRV_CROSS_UTIL_HPP
#define SPIRV_CROSS_UTIL_HPP
#include "spirv_cross.hpp"
namespace spirv_cross_util
{
void rename_interface_variable(SPIRV_CROSS_NAMESPACE::Compiler &compiler,
const SPIRV_CROSS_NAMESPACE::SmallVector<SPIRV_CROSS_NAMESPACE::Resource> &resources,
uint32_t location, const std::string &name);
void inherit_combined_sampler_bindings(SPIRV_CROSS_NAMESPACE::Compiler &compiler);
} // namespace spirv_cross_util
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-357
View File
@@ -1,357 +0,0 @@
/*
* Copyright 2016-2020 Robert Konrad
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SPIRV_HLSL_HPP
#define SPIRV_HLSL_HPP
#include "spirv_glsl.hpp"
#include <utility>
namespace SPIRV_CROSS_NAMESPACE
{
// Interface which remaps vertex inputs to a fixed semantic name to make linking easier.
struct HLSLVertexAttributeRemap
{
uint32_t location;
std::string semantic;
};
// Specifying a root constant (d3d12) or push constant range (vulkan).
//
// `start` and `end` denotes the range of the root constant in bytes.
// Both values need to be multiple of 4.
struct RootConstants
{
uint32_t start;
uint32_t end;
uint32_t binding;
uint32_t space;
};
// For finer control, decorations may be removed from specific resources instead with unset_decoration().
enum HLSLBindingFlagBits
{
HLSL_BINDING_AUTO_NONE_BIT = 0,
// Push constant (root constant) resources will be declared as CBVs (b-space) without a register() declaration.
// A register will be automatically assigned by the D3D compiler, but must therefore be reflected in D3D-land.
// Push constants do not normally have a DecorationBinding set, but if they do, this can be used to ignore it.
HLSL_BINDING_AUTO_PUSH_CONSTANT_BIT = 1 << 0,
// cbuffer resources will be declared as CBVs (b-space) without a register() declaration.
// A register will be automatically assigned, but must be reflected in D3D-land.
HLSL_BINDING_AUTO_CBV_BIT = 1 << 1,
// All SRVs (t-space) will be declared without a register() declaration.
HLSL_BINDING_AUTO_SRV_BIT = 1 << 2,
// All UAVs (u-space) will be declared without a register() declaration.
HLSL_BINDING_AUTO_UAV_BIT = 1 << 3,
// All samplers (s-space) will be declared without a register() declaration.
HLSL_BINDING_AUTO_SAMPLER_BIT = 1 << 4,
// No resources will be declared with register().
HLSL_BINDING_AUTO_ALL = 0x7fffffff
};
using HLSLBindingFlags = uint32_t;
// By matching stage, desc_set and binding for a SPIR-V resource,
// register bindings are set based on whether the HLSL resource is a
// CBV, UAV, SRV or Sampler. A single binding in SPIR-V might contain multiple
// resource types, e.g. COMBINED_IMAGE_SAMPLER, and SRV/Sampler bindings will be used respectively.
// On SM 5.0 and lower, register_space is ignored.
//
// To remap a push constant block which does not have any desc_set/binding associated with it,
// use ResourceBindingPushConstant{DescriptorSet,Binding} as values for desc_set/binding.
// For deeper control of push constants, set_root_constant_layouts() can be used instead.
struct HLSLResourceBinding
{
spv::ExecutionModel stage = spv::ExecutionModelMax;
uint32_t desc_set = 0;
uint32_t binding = 0;
struct Binding
{
uint32_t register_space = 0;
uint32_t register_binding = 0;
} cbv, uav, srv, sampler;
};
class CompilerHLSL : public CompilerGLSL
{
public:
struct Options
{
uint32_t shader_model = 30; // TODO: map ps_4_0_level_9_0,... somehow
// Allows the PointSize builtin, and ignores it, as PointSize is not supported in HLSL.
bool point_size_compat = false;
// Allows the PointCoord builtin, returns float2(0.5, 0.5), as PointCoord is not supported in HLSL.
bool point_coord_compat = false;
// If true, the backend will assume that VertexIndex and InstanceIndex will need to apply
// a base offset, and you will need to fill in a cbuffer with offsets.
// Set to false if you know you will never use base instance or base vertex
// functionality as it might remove an internal cbuffer.
bool support_nonzero_base_vertex_base_instance = false;
// Forces a storage buffer to always be declared as UAV, even if the readonly decoration is used.
// By default, a readonly storage buffer will be declared as ByteAddressBuffer (SRV) instead.
// Alternatively, use set_hlsl_force_storage_buffer_as_uav to specify individually.
bool force_storage_buffer_as_uav = false;
// Forces any storage image type marked as NonWritable to be considered an SRV instead.
// For this to work with function call parameters, NonWritable must be considered to be part of the type system
// so that NonWritable image arguments are also translated to Texture rather than RWTexture.
bool nonwritable_uav_texture_as_srv = false;
// Enables native 16-bit types. Needs SM 6.2.
// Uses half/int16_t/uint16_t instead of min16* types.
// Also adds support for 16-bit load-store from (RW)ByteAddressBuffer.
bool enable_16bit_types = false;
};
explicit CompilerHLSL(std::vector<uint32_t> spirv_)
: CompilerGLSL(std::move(spirv_))
{
}
CompilerHLSL(const uint32_t *ir_, size_t size)
: CompilerGLSL(ir_, size)
{
}
explicit CompilerHLSL(const ParsedIR &ir_)
: CompilerGLSL(ir_)
{
}
explicit CompilerHLSL(ParsedIR &&ir_)
: CompilerGLSL(std::move(ir_))
{
}
const Options &get_hlsl_options() const
{
return hlsl_options;
}
void set_hlsl_options(const Options &opts)
{
hlsl_options = opts;
}
// Optionally specify a custom root constant layout.
//
// Push constants ranges will be split up according to the
// layout specified.
void set_root_constant_layouts(std::vector<RootConstants> layout);
// Compiles and remaps vertex attributes at specific locations to a fixed semantic.
// The default is TEXCOORD# where # denotes location.
// Matrices are unrolled to vectors with notation ${SEMANTIC}_#, where # denotes row.
// $SEMANTIC is either TEXCOORD# or a semantic name specified here.
void add_vertex_attribute_remap(const HLSLVertexAttributeRemap &vertex_attributes);
std::string compile() override;
// This is a special HLSL workaround for the NumWorkGroups builtin.
// This does not exist in HLSL, so the calling application must create a dummy cbuffer in
// which the application will store this builtin.
// The cbuffer layout will be:
// cbuffer SPIRV_Cross_NumWorkgroups : register(b#, space#) { uint3 SPIRV_Cross_NumWorkgroups_count; };
// This must be called before compile().
// The function returns 0 if NumWorkGroups builtin is not statically used in the shader from the current entry point.
// If non-zero, this returns the variable ID of a cbuffer which corresponds to
// the cbuffer declared above. By default, no binding or descriptor set decoration is set,
// so the calling application should declare explicit bindings on this ID before calling compile().
VariableID remap_num_workgroups_builtin();
// Controls how resource bindings are declared in the output HLSL.
void set_resource_binding_flags(HLSLBindingFlags flags);
// resource is a resource binding to indicate the HLSL CBV, SRV, UAV or sampler binding
// to use for a particular SPIR-V description set
// and binding. If resource bindings are provided,
// is_hlsl_resource_binding_used() will return true after calling ::compile() if
// the set/binding combination was used by the HLSL code.
void add_hlsl_resource_binding(const HLSLResourceBinding &resource);
bool is_hlsl_resource_binding_used(spv::ExecutionModel model, uint32_t set, uint32_t binding) const;
// Controls which storage buffer bindings will be forced to be declared as UAVs.
void set_hlsl_force_storage_buffer_as_uav(uint32_t desc_set, uint32_t binding);
private:
std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override;
std::string image_type_hlsl(const SPIRType &type, uint32_t id);
std::string image_type_hlsl_modern(const SPIRType &type, uint32_t id);
std::string image_type_hlsl_legacy(const SPIRType &type, uint32_t id);
void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) override;
void emit_hlsl_entry_point();
void emit_header() override;
void emit_resources();
void declare_undefined_values() override;
void emit_interface_block_globally(const SPIRVariable &type);
void emit_interface_block_in_struct(const SPIRVariable &type, std::unordered_set<uint32_t> &active_locations);
void emit_builtin_inputs_in_struct();
void emit_builtin_outputs_in_struct();
void emit_texture_op(const Instruction &i, bool sparse) override;
void emit_instruction(const Instruction &instruction) override;
void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args,
uint32_t count) override;
void emit_buffer_block(const SPIRVariable &type) override;
void emit_push_constant_block(const SPIRVariable &var) override;
void emit_uniform(const SPIRVariable &var) override;
void emit_modern_uniform(const SPIRVariable &var);
void emit_legacy_uniform(const SPIRVariable &var);
void emit_specialization_constants_and_structs();
void emit_composite_constants();
void emit_fixup() override;
std::string builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClass storage) override;
std::string layout_for_member(const SPIRType &type, uint32_t index) override;
std::string to_interpolation_qualifiers(const Bitset &flags) override;
std::string bitcast_glsl_op(const SPIRType &result_type, const SPIRType &argument_type) override;
bool emit_complex_bitcast(uint32_t result_type, uint32_t id, uint32_t op0) override;
std::string to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id) override;
std::string to_sampler_expression(uint32_t id);
std::string to_resource_binding(const SPIRVariable &var);
std::string to_resource_binding_sampler(const SPIRVariable &var);
std::string to_resource_register(HLSLBindingFlagBits flag, char space, uint32_t binding, uint32_t set);
void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id) override;
void emit_access_chain(const Instruction &instruction);
void emit_load(const Instruction &instruction);
void read_access_chain(std::string *expr, const std::string &lhs, const SPIRAccessChain &chain);
void read_access_chain_struct(const std::string &lhs, const SPIRAccessChain &chain);
void read_access_chain_array(const std::string &lhs, const SPIRAccessChain &chain);
void write_access_chain(const SPIRAccessChain &chain, uint32_t value, const SmallVector<uint32_t> &composite_chain);
void write_access_chain_struct(const SPIRAccessChain &chain, uint32_t value,
const SmallVector<uint32_t> &composite_chain);
void write_access_chain_array(const SPIRAccessChain &chain, uint32_t value,
const SmallVector<uint32_t> &composite_chain);
std::string write_access_chain_value(uint32_t value, const SmallVector<uint32_t> &composite_chain, bool enclose);
void emit_store(const Instruction &instruction);
void emit_atomic(const uint32_t *ops, uint32_t length, spv::Op op);
void emit_subgroup_op(const Instruction &i) override;
void emit_block_hints(const SPIRBlock &block) override;
void emit_struct_member(const SPIRType &type, uint32_t member_type_id, uint32_t index, const std::string &qualifier,
uint32_t base_offset = 0) override;
const char *to_storage_qualifiers_glsl(const SPIRVariable &var) override;
void replace_illegal_names() override;
bool is_hlsl_force_storage_buffer_as_uav(ID id) const;
Options hlsl_options;
// TODO: Refactor this to be more similar to MSL, maybe have some common system in place?
bool requires_op_fmod = false;
bool requires_fp16_packing = false;
bool requires_uint2_packing = false;
bool requires_explicit_fp16_packing = false;
bool requires_unorm8_packing = false;
bool requires_snorm8_packing = false;
bool requires_unorm16_packing = false;
bool requires_snorm16_packing = false;
bool requires_bitfield_insert = false;
bool requires_bitfield_extract = false;
bool requires_inverse_2x2 = false;
bool requires_inverse_3x3 = false;
bool requires_inverse_4x4 = false;
bool requires_scalar_reflect = false;
bool requires_scalar_refract = false;
bool requires_scalar_faceforward = false;
struct TextureSizeVariants
{
// MSVC 2013 workaround.
TextureSizeVariants()
{
srv = 0;
for (auto &unorm : uav)
for (auto &u : unorm)
u = 0;
}
uint64_t srv;
uint64_t uav[3][4];
} required_texture_size_variants;
void require_texture_query_variant(uint32_t var_id);
void emit_texture_size_variants(uint64_t variant_mask, const char *vecsize_qualifier, bool uav, const char *type_qualifier);
enum TextureQueryVariantDim
{
Query1D = 0,
Query1DArray,
Query2D,
Query2DArray,
Query3D,
QueryBuffer,
QueryCube,
QueryCubeArray,
Query2DMS,
Query2DMSArray,
QueryDimCount
};
enum TextureQueryVariantType
{
QueryTypeFloat = 0,
QueryTypeInt = 16,
QueryTypeUInt = 32,
QueryTypeCount = 3
};
enum BitcastType
{
TypeNormal,
TypePackUint2x32,
TypeUnpackUint64
};
BitcastType get_bitcast_type(uint32_t result_type, uint32_t op0);
void emit_builtin_variables();
bool require_output = false;
bool require_input = false;
SmallVector<HLSLVertexAttributeRemap> remap_vertex_attributes;
uint32_t type_to_consumed_locations(const SPIRType &type) const;
void emit_io_block(const SPIRVariable &var);
std::string to_semantic(uint32_t location, spv::ExecutionModel em, spv::StorageClass sc);
uint32_t num_workgroups_builtin = 0;
HLSLBindingFlags resource_binding_flags = 0;
// Custom root constant layout, which should be emitted
// when translating push constant ranges.
std::vector<RootConstants> root_constants_layout;
void validate_shader_model();
std::string get_unique_identifier();
uint32_t unique_identifier_count = 0;
std::unordered_map<StageSetBinding, std::pair<HLSLResourceBinding, bool>, InternalHasher> resource_bindings;
void remap_hlsl_resource_binding(HLSLBindingFlagBits type, uint32_t &desc_set, uint32_t &binding);
std::unordered_set<SetBindingPair, InternalHasher> force_uav_buffer_bindings;
};
} // namespace SPIRV_CROSS_NAMESPACE
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-94
View File
@@ -1,94 +0,0 @@
/*
* Copyright 2018-2020 Arm Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SPIRV_CROSS_PARSER_HPP
#define SPIRV_CROSS_PARSER_HPP
#include "spirv_cross_parsed_ir.hpp"
#include <stdint.h>
namespace SPIRV_CROSS_NAMESPACE
{
class Parser
{
public:
Parser(const uint32_t *spirv_data, size_t word_count);
Parser(std::vector<uint32_t> spirv);
void parse();
ParsedIR &get_parsed_ir()
{
return ir;
}
private:
ParsedIR ir;
SPIRFunction *current_function = nullptr;
SPIRBlock *current_block = nullptr;
void parse(const Instruction &instr);
const uint32_t *stream(const Instruction &instr) const;
template <typename T, typename... P>
T &set(uint32_t id, P &&... args)
{
ir.add_typed_id(static_cast<Types>(T::type), id);
auto &var = variant_set<T>(ir.ids[id], std::forward<P>(args)...);
var.self = id;
return var;
}
template <typename T>
T &get(uint32_t id)
{
return variant_get<T>(ir.ids[id]);
}
template <typename T>
T *maybe_get(uint32_t id)
{
if (ir.ids[id].get_type() == static_cast<Types>(T::type))
return &get<T>(id);
else
return nullptr;
}
template <typename T>
const T &get(uint32_t id) const
{
return variant_get<T>(ir.ids[id]);
}
template <typename T>
const T *maybe_get(uint32_t id) const
{
if (ir.ids[id].get_type() == T::type)
return &get<T>(id);
else
return nullptr;
}
// This must be an ordered data structure so we always pick the same type aliases.
SmallVector<uint32_t> global_struct_cache;
SmallVector<std::pair<uint32_t, uint32_t>> forward_pointer_fixups;
bool types_are_logically_equivalent(const SPIRType &a, const SPIRType &b) const;
bool variable_storage_is_aliased(const SPIRVariable &v) const;
};
} // namespace SPIRV_CROSS_NAMESPACE
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-84
View File
@@ -1,84 +0,0 @@
/*
* Copyright 2018-2020 Bradley Austin Davis
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SPIRV_CROSS_REFLECT_HPP
#define SPIRV_CROSS_REFLECT_HPP
#include "spirv_glsl.hpp"
#include <utility>
namespace simple_json
{
class Stream;
}
namespace SPIRV_CROSS_NAMESPACE
{
class CompilerReflection : public CompilerGLSL
{
using Parent = CompilerGLSL;
public:
explicit CompilerReflection(std::vector<uint32_t> spirv_)
: Parent(std::move(spirv_))
{
options.vulkan_semantics = true;
}
CompilerReflection(const uint32_t *ir_, size_t word_count)
: Parent(ir_, word_count)
{
options.vulkan_semantics = true;
}
explicit CompilerReflection(const ParsedIR &ir_)
: CompilerGLSL(ir_)
{
options.vulkan_semantics = true;
}
explicit CompilerReflection(ParsedIR &&ir_)
: CompilerGLSL(std::move(ir_))
{
options.vulkan_semantics = true;
}
void set_format(const std::string &format);
std::string compile() override;
private:
static std::string execution_model_to_str(spv::ExecutionModel model);
void emit_entry_points();
void emit_types();
void emit_resources();
void emit_specialization_constants();
void emit_type(uint32_t type_id, bool &emitted_open_tag);
void emit_type_member(const SPIRType &type, uint32_t index);
void emit_type_member_qualifiers(const SPIRType &type, uint32_t index);
void emit_type_array(const SPIRType &type);
void emit_resources(const char *tag, const SmallVector<Resource> &resources);
bool type_is_reference(const SPIRType &type) const;
std::string to_member_name(const SPIRType &type, uint32_t index) const;
std::shared_ptr<simple_json::Stream> json_stream;
};
} // namespace SPIRV_CROSS_NAMESPACE
#endif
+12 -27
View File
@@ -254,24 +254,10 @@
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\DirectXMathCommon.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\DirectXPackedVector.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\GLSL.std.450.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\include\spirv\unified1\spirv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\replace_new.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\sal.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cfg.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_common.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cpp.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cross.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_c.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_containers.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_error_handling.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_parsed_ir.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_util.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_glsl.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_hlsl.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_msl.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_parser.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_reflect.hpp" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_reflect.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\stb_image.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\stb_image_write.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\stb_truetype.h" />
@@ -529,17 +515,16 @@
<ClCompile Include="$(MSBuildThisFileDirectory)BULLET\LinearMath\btVector3.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)RenderPath3D_PathTracing.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\D3D12MemAlloc.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_cfg.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_cpp.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_cross.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_c.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_parsed_ir.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_util.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_glsl.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_hlsl.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_msl.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_parser.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_reflect.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_reflect.c">
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">false</CompileAsWinRT>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\stb_vorbis.c">
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsWinRT>
@@ -1116,54 +1116,6 @@
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\DirectXMathCommon.h">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cross.hpp">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_reflect.hpp">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_glsl.hpp">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_hlsl.hpp">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv.h">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv.hpp">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cfg.hpp">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_common.hpp">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cpp.hpp">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_c.h">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_containers.hpp">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_error_handling.hpp">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_parsed_ir.hpp">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_util.hpp">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_msl.hpp">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_parser.hpp">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\GLSL.std.450.h">
<Filter>UTILITY</Filter>
</ClInclude>
@@ -1173,6 +1125,12 @@
<ClInclude Include="$(MSBuildThisFileDirectory)wiSDLInput.h">
<Filter>ENGINE\Input</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\spirv_reflect.h">
<Filter>UTILITY</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)Utility\include\spirv\unified1\spirv.h">
<Filter>UTILITY</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)LUA\lapi.c">
@@ -1907,39 +1865,6 @@
<ClCompile Include="$(MSBuildThisFileDirectory)wiNetwork_Linux.cpp">
<Filter>ENGINE\Network</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_cross.cpp">
<Filter>UTILITY</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_reflect.cpp">
<Filter>UTILITY</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_glsl.cpp">
<Filter>UTILITY</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_hlsl.cpp">
<Filter>UTILITY</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_cfg.cpp">
<Filter>UTILITY</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_cpp.cpp">
<Filter>UTILITY</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_c.cpp">
<Filter>UTILITY</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_parsed_ir.cpp">
<Filter>UTILITY</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_cross_util.cpp">
<Filter>UTILITY</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_msl.cpp">
<Filter>UTILITY</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_parser.cpp">
<Filter>UTILITY</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)wiEvent.cpp">
<Filter>ENGINE\System</Filter>
</ClCompile>
@@ -1949,6 +1874,9 @@
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\stb_vorbis.c">
<Filter>UTILITY</Filter>
</ClCompile>
<ClCompile Include="$(MSBuildThisFileDirectory)Utility\spirv_reflect.c">
<Filter>UTILITY</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="$(MSBuildThisFileDirectory)ArchiveVersionHistory.txt" />
+5 -1
View File
@@ -58,7 +58,6 @@ for item in root.iter():
cmd += "_6_5 "
cmd += " -spirv "
cmd += " -fspv-target-env=vulkan1.2 "
cmd += " -fvk-use-dx-layout "
cmd += " -fvk-use-dx-position-w "
cmd += " -flegacy-macro-expansion "
@@ -66,6 +65,11 @@ for item in root.iter():
if profile == "VS" or profile == "DS" or profile == "GS":
cmd += " -fvk-invert-y "
if profile == "LIB":
cmd += " -fspv-target-env=vulkan1.2 "
else:
cmd += " -fspv-target-env=vulkan1.1 "
#cmd += " -fvk-b-shift 0 all "
cmd += " -fvk-t-shift 1000 all "
cmd += " -fvk-u-shift 2000 all "
+88 -158
View File
@@ -3,7 +3,7 @@
#ifdef WICKEDENGINE_BUILD_VULKAN
#pragma comment(lib,"vulkan-1.lib")
#include "Utility/spirv_reflect.hpp"
#include "Utility/spirv_reflect.h"
#include "wiGraphicsDevice_SharedInternals.h"
#include "wiHelper.h"
@@ -983,8 +983,6 @@ namespace Vulkan_Internal
std::vector<VkDescriptorSetLayoutBinding> layoutBindings;
std::vector<VkImageViewType> imageViewTypes;
std::vector<spirv_cross::EntryPoint> entrypoints;
~Shader_Vulkan()
{
if (allocationhandler == nullptr)
@@ -3753,174 +3751,106 @@ using namespace Vulkan_Internal;
if (pShader->rootSignature == nullptr)
{
// Perform shader reflection for shaders that don't specify a root signature:
spirv_cross::Compiler comp((uint32_t*)pShader->code.data(), pShader->code.size() / sizeof(uint32_t));
auto entrypoints = comp.get_entry_points_and_stages();
auto active = comp.get_active_interface_variables();
spirv_cross::ShaderResources resources = comp.get_shader_resources(active);
comp.set_enabled_interface_variables(move(active));
internal_state->entrypoints.reserve(entrypoints.size());
for (auto& x : entrypoints)
{
internal_state->entrypoints.push_back(x);
}
SpvReflectShaderModule module;
SpvReflectResult result = spvReflectCreateShaderModule(moduleInfo.codeSize, moduleInfo.pCode, &module);
assert(result == SPV_REFLECT_RESULT_SUCCESS);
uint32_t binding_count = 0;
result = spvReflectEnumerateEntryPointDescriptorBindings(
&module, internal_state->stageInfo.pName, &binding_count, nullptr
);
assert(result == SPV_REFLECT_RESULT_SUCCESS);
std::vector<SpvReflectDescriptorBinding*> bindings(binding_count);
result = spvReflectEnumerateEntryPointDescriptorBindings(
&module, internal_state->stageInfo.pName, &binding_count, bindings.data()
);
assert(result == SPV_REFLECT_RESULT_SUCCESS);
std::vector<VkDescriptorSetLayoutBinding>& layoutBindings = internal_state->layoutBindings;
std::vector<VkImageViewType>& imageViewTypes = internal_state->imageViewTypes;
for (auto& x : resources.separate_samplers)
for (auto& x : bindings)
{
VkDescriptorSetLayoutBinding layoutBinding = {};
layoutBinding.stageFlags = internal_state->stageInfo.stage;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
layoutBinding.binding = comp.get_decoration(x.id, spv::Decoration::DecorationBinding);
layoutBinding.descriptorCount = 1;
layoutBindings.push_back(layoutBinding);
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM);
}
for (auto& x : resources.separate_images)
{
VkDescriptorSetLayoutBinding layoutBinding = {};
layoutBinding.stageFlags = internal_state->stageInfo.stage;
auto image = comp.get_type_from_variable(x.id).image;
switch (image.dim)
layoutBindings.emplace_back();
layoutBindings.back().stageFlags = internal_state->stageInfo.stage;
layoutBindings.back().binding = x->binding;
layoutBindings.back().descriptorCount = 1;
switch (x->descriptor_type)
{
case spv::Dim1D:
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
if (image.arrayed)
{
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_1D_ARRAY);
}
else
{
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_1D);
}
break;
case spv::Dim2D:
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
if (image.arrayed)
{
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_2D_ARRAY);
}
else
{
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_2D);
}
break;
case spv::Dim3D:
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_3D);
break;
case spv::DimCube:
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
if (image.arrayed)
{
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
}
else
{
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_CUBE);
}
break;
case spv::DimBuffer:
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM);
break;
default:
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM);
case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLER:
case SPV_REFLECT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
layoutBindings.back().descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
break;
case SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_IMAGE:
if (x->descriptor_type == SPV_REFLECT_DESCRIPTOR_TYPE_SAMPLED_IMAGE)
{
layoutBindings.back().descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
}
else
{
layoutBindings.back().descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
}
switch (x->image.dim)
{
default:
case SpvDim1D:
if (x->image.arrayed == 0)
{
imageViewTypes.back() = VK_IMAGE_VIEW_TYPE_1D;
}
else
{
imageViewTypes.back() = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
}
break;
case SpvDim2D:
if (x->image.arrayed == 0)
{
imageViewTypes.back() = VK_IMAGE_VIEW_TYPE_2D;
}
else
{
imageViewTypes.back() = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
}
break;
case SpvDim3D:
imageViewTypes.back() = VK_IMAGE_VIEW_TYPE_3D;
break;
case SpvDimCube:
if (x->image.arrayed == 0)
{
imageViewTypes.back() = VK_IMAGE_VIEW_TYPE_CUBE;
}
else
{
imageViewTypes.back() = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
}
break;
}
break;
case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
layoutBindings.back().descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
break;
case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_BUFFER:
layoutBindings.back().descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
break;
case SPV_REFLECT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
layoutBindings.back().descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
break;
case SPV_REFLECT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
layoutBindings.back().descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
break;
}
layoutBinding.binding = comp.get_decoration(x.id, spv::Decoration::DecorationBinding);
layoutBinding.descriptorCount = 1;
layoutBindings.push_back(layoutBinding);
}
for (auto& x : resources.storage_images)
{
VkDescriptorSetLayoutBinding layoutBinding = {};
layoutBinding.stageFlags = internal_state->stageInfo.stage;
auto image = comp.get_type_from_variable(x.id).image;
switch (image.dim)
{
case spv::Dim1D:
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
if (image.arrayed)
{
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_1D_ARRAY);
}
else
{
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_1D);
}
break;
case spv::Dim2D:
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
if (image.arrayed)
{
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_2D_ARRAY);
}
else
{
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_2D);
}
break;
case spv::Dim3D:
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_3D);
break;
case spv::DimCube:
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
if (image.arrayed)
{
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_CUBE_ARRAY);
}
else
{
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_CUBE);
}
break;
case spv::DimBuffer:
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM);
break;
default:
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM);
break;
}
layoutBinding.binding = comp.get_decoration(x.id, spv::Decoration::DecorationBinding);
layoutBinding.descriptorCount = 1;
layoutBindings.push_back(layoutBinding);
}
for (auto& x : resources.uniform_buffers)
{
VkDescriptorSetLayoutBinding layoutBinding = {};
layoutBinding.stageFlags = internal_state->stageInfo.stage;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
layoutBinding.binding = comp.get_decoration(x.id, spv::Decoration::DecorationBinding);
layoutBinding.descriptorCount = 1;
layoutBindings.push_back(layoutBinding);
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM);
}
for (auto& x : resources.storage_buffers)
{
VkDescriptorSetLayoutBinding layoutBinding = {};
layoutBinding.stageFlags = internal_state->stageInfo.stage;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
layoutBinding.binding = comp.get_decoration(x.id, spv::Decoration::DecorationBinding);
layoutBinding.descriptorCount = 1;
layoutBindings.push_back(layoutBinding);
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM);
}
for (auto& x : resources.acceleration_structures)
{
VkDescriptorSetLayoutBinding layoutBinding = {};
layoutBinding.stageFlags = internal_state->stageInfo.stage;
layoutBinding.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
layoutBinding.binding = comp.get_decoration(x.id, spv::Decoration::DecorationBinding);
layoutBinding.descriptorCount = 1;
layoutBindings.push_back(layoutBinding);
imageViewTypes.push_back(VK_IMAGE_VIEW_TYPE_MAX_ENUM);
}
spvReflectDestroyShaderModule(&module);
if (stage == CS || stage == SHADERSTAGE_COUNT)
{
VkDescriptorSetLayoutCreateInfo descriptorSetlayoutInfo = {};
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates, breaking API changes
const int minor = 49;
// minor bug fixes, alterations, refactors, updates
const int revision = 19;
const int revision = 20;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);