mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-18 00:35:46 -04:00
dep: Add SPIRV-Cross
This commit is contained in:
114
dep/spirv-cross/include/spirv-cross/GLSL.std.450.h
Normal file
114
dep/spirv-cross/include/spirv-cross/GLSL.std.450.h
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2014-2016,2021 The Khronos Group, Inc.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS
|
||||
* STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND
|
||||
* HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/
|
||||
*/
|
||||
|
||||
#ifndef GLSLstd450_H
|
||||
#define GLSLstd450_H
|
||||
|
||||
static const int GLSLstd450Version = 100;
|
||||
static const int GLSLstd450Revision = 3;
|
||||
|
||||
enum GLSLstd450 {
|
||||
GLSLstd450Bad = 0, // Don't use
|
||||
|
||||
GLSLstd450Round = 1,
|
||||
GLSLstd450RoundEven = 2,
|
||||
GLSLstd450Trunc = 3,
|
||||
GLSLstd450FAbs = 4,
|
||||
GLSLstd450SAbs = 5,
|
||||
GLSLstd450FSign = 6,
|
||||
GLSLstd450SSign = 7,
|
||||
GLSLstd450Floor = 8,
|
||||
GLSLstd450Ceil = 9,
|
||||
GLSLstd450Fract = 10,
|
||||
|
||||
GLSLstd450Radians = 11,
|
||||
GLSLstd450Degrees = 12,
|
||||
GLSLstd450Sin = 13,
|
||||
GLSLstd450Cos = 14,
|
||||
GLSLstd450Tan = 15,
|
||||
GLSLstd450Asin = 16,
|
||||
GLSLstd450Acos = 17,
|
||||
GLSLstd450Atan = 18,
|
||||
GLSLstd450Sinh = 19,
|
||||
GLSLstd450Cosh = 20,
|
||||
GLSLstd450Tanh = 21,
|
||||
GLSLstd450Asinh = 22,
|
||||
GLSLstd450Acosh = 23,
|
||||
GLSLstd450Atanh = 24,
|
||||
GLSLstd450Atan2 = 25,
|
||||
|
||||
GLSLstd450Pow = 26,
|
||||
GLSLstd450Exp = 27,
|
||||
GLSLstd450Log = 28,
|
||||
GLSLstd450Exp2 = 29,
|
||||
GLSLstd450Log2 = 30,
|
||||
GLSLstd450Sqrt = 31,
|
||||
GLSLstd450InverseSqrt = 32,
|
||||
|
||||
GLSLstd450Determinant = 33,
|
||||
GLSLstd450MatrixInverse = 34,
|
||||
|
||||
GLSLstd450Modf = 35, // second operand needs an OpVariable to write to
|
||||
GLSLstd450ModfStruct = 36, // no OpVariable operand
|
||||
GLSLstd450FMin = 37,
|
||||
GLSLstd450UMin = 38,
|
||||
GLSLstd450SMin = 39,
|
||||
GLSLstd450FMax = 40,
|
||||
GLSLstd450UMax = 41,
|
||||
GLSLstd450SMax = 42,
|
||||
GLSLstd450FClamp = 43,
|
||||
GLSLstd450UClamp = 44,
|
||||
GLSLstd450SClamp = 45,
|
||||
GLSLstd450FMix = 46,
|
||||
GLSLstd450IMix = 47, // Reserved
|
||||
GLSLstd450Step = 48,
|
||||
GLSLstd450SmoothStep = 49,
|
||||
|
||||
GLSLstd450Fma = 50,
|
||||
GLSLstd450Frexp = 51, // second operand needs an OpVariable to write to
|
||||
GLSLstd450FrexpStruct = 52, // no OpVariable operand
|
||||
GLSLstd450Ldexp = 53,
|
||||
|
||||
GLSLstd450PackSnorm4x8 = 54,
|
||||
GLSLstd450PackUnorm4x8 = 55,
|
||||
GLSLstd450PackSnorm2x16 = 56,
|
||||
GLSLstd450PackUnorm2x16 = 57,
|
||||
GLSLstd450PackHalf2x16 = 58,
|
||||
GLSLstd450PackDouble2x32 = 59,
|
||||
GLSLstd450UnpackSnorm2x16 = 60,
|
||||
GLSLstd450UnpackUnorm2x16 = 61,
|
||||
GLSLstd450UnpackHalf2x16 = 62,
|
||||
GLSLstd450UnpackSnorm4x8 = 63,
|
||||
GLSLstd450UnpackUnorm4x8 = 64,
|
||||
GLSLstd450UnpackDouble2x32 = 65,
|
||||
|
||||
GLSLstd450Length = 66,
|
||||
GLSLstd450Distance = 67,
|
||||
GLSLstd450Cross = 68,
|
||||
GLSLstd450Normalize = 69,
|
||||
GLSLstd450FaceForward = 70,
|
||||
GLSLstd450Reflect = 71,
|
||||
GLSLstd450Refract = 72,
|
||||
|
||||
GLSLstd450FindILsb = 73,
|
||||
GLSLstd450FindSMsb = 74,
|
||||
GLSLstd450FindUMsb = 75,
|
||||
|
||||
GLSLstd450InterpolateAtCentroid = 76,
|
||||
GLSLstd450InterpolateAtSample = 77,
|
||||
GLSLstd450InterpolateAtOffset = 78,
|
||||
|
||||
GLSLstd450NMin = 79,
|
||||
GLSLstd450NMax = 80,
|
||||
GLSLstd450NClamp = 81,
|
||||
|
||||
GLSLstd450Count
|
||||
};
|
||||
|
||||
#endif // #ifndef GLSLstd450_H
|
2568
dep/spirv-cross/include/spirv-cross/spirv.h
Normal file
2568
dep/spirv-cross/include/spirv-cross/spirv.h
Normal file
File diff suppressed because it is too large
Load Diff
2579
dep/spirv-cross/include/spirv-cross/spirv.hpp
Normal file
2579
dep/spirv-cross/include/spirv-cross/spirv.hpp
Normal file
File diff suppressed because it is too large
Load Diff
168
dep/spirv-cross/include/spirv-cross/spirv_cfg.hpp
Normal file
168
dep/spirv-cross/include/spirv-cross/spirv_cfg.hpp
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Arm Limited
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* At your option, you may choose to accept this material under either:
|
||||
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
|
||||
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
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);
|
||||
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
|
1921
dep/spirv-cross/include/spirv-cross/spirv_common.hpp
Normal file
1921
dep/spirv-cross/include/spirv-cross/spirv_common.hpp
Normal file
File diff suppressed because it is too large
Load Diff
93
dep/spirv-cross/include/spirv-cross/spirv_cpp.hpp
Normal file
93
dep/spirv-cross/include/spirv-cross/spirv_cpp.hpp
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2015-2021 Arm Limited
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* At your option, you may choose to accept this material under either:
|
||||
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
|
||||
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
|
||||
*/
|
||||
|
||||
#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
|
1175
dep/spirv-cross/include/spirv-cross/spirv_cross.hpp
Normal file
1175
dep/spirv-cross/include/spirv-cross/spirv_cross.hpp
Normal file
File diff suppressed because it is too large
Load Diff
755
dep/spirv-cross/include/spirv-cross/spirv_cross_containers.hpp
Normal file
755
dep/spirv-cross/include/spirv-cross/spirv_cross_containers.hpp
Normal file
@ -0,0 +1,755 @@
|
||||
/*
|
||||
* Copyright 2019-2021 Hans-Kristian Arntzen
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* At your option, you may choose to accept this material under either:
|
||||
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
|
||||
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
|
||||
*/
|
||||
|
||||
#ifndef SPIRV_CROSS_CONTAINERS_HPP
|
||||
#define SPIRV_CROSS_CONTAINERS_HPP
|
||||
|
||||
#include "spirv_cross_error_handling.hpp"
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <stack>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#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
|
||||
{
|
||||
#ifndef SPIRV_CROSS_FORCE_STL_TYPES
|
||||
// std::aligned_storage does not support size == 0, so roll our own.
|
||||
template <typename T, size_t N>
|
||||
class AlignedBuffer
|
||||
{
|
||||
public:
|
||||
T *data()
|
||||
{
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
// MSVC 2013 workarounds, sigh ...
|
||||
// Only use this workaround on MSVC 2013 due to some confusion around default initialized unions.
|
||||
// Spec seems to suggest the memory will be zero-initialized, which is *not* what we want.
|
||||
return reinterpret_cast<T *>(u.aligned_char);
|
||||
#else
|
||||
return reinterpret_cast<T *>(aligned_char);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
// MSVC 2013 workarounds, sigh ...
|
||||
union
|
||||
{
|
||||
char aligned_char[sizeof(T) * N];
|
||||
double dummy_aligner;
|
||||
} u;
|
||||
#else
|
||||
alignas(T) char aligned_char[sizeof(T) * N];
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class AlignedBuffer<T, 0>
|
||||
{
|
||||
public:
|
||||
T *data()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
// An immutable version of SmallVector which erases type information about storage.
|
||||
template <typename T>
|
||||
class VectorView
|
||||
{
|
||||
public:
|
||||
T &operator[](size_t i) SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
return ptr[i];
|
||||
}
|
||||
|
||||
const T &operator[](size_t i) const SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
return ptr[i];
|
||||
}
|
||||
|
||||
bool empty() const SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
return buffer_size == 0;
|
||||
}
|
||||
|
||||
size_t size() const SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
return buffer_size;
|
||||
}
|
||||
|
||||
T *data() SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
const T *data() const SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
T *begin() SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
T *end() SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
return ptr + buffer_size;
|
||||
}
|
||||
|
||||
const T *begin() const SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
const T *end() const SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
return ptr + buffer_size;
|
||||
}
|
||||
|
||||
T &front() SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
return ptr[0];
|
||||
}
|
||||
|
||||
const T &front() const SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
return ptr[0];
|
||||
}
|
||||
|
||||
T &back() SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
return ptr[buffer_size - 1];
|
||||
}
|
||||
|
||||
const T &back() const SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
return ptr[buffer_size - 1];
|
||||
}
|
||||
|
||||
// Makes it easier to consume SmallVector.
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
explicit operator std::vector<T>() const
|
||||
{
|
||||
// Another MSVC 2013 workaround. It does not understand lvalue/rvalue qualified operations.
|
||||
return std::vector<T>(ptr, ptr + buffer_size);
|
||||
}
|
||||
#else
|
||||
// Makes it easier to consume SmallVector.
|
||||
explicit operator std::vector<T>() const &
|
||||
{
|
||||
return std::vector<T>(ptr, ptr + buffer_size);
|
||||
}
|
||||
|
||||
// If we are converting as an r-value, we can pilfer our elements.
|
||||
explicit operator std::vector<T>() &&
|
||||
{
|
||||
return std::vector<T>(std::make_move_iterator(ptr), std::make_move_iterator(ptr + buffer_size));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Avoid sliced copies. Base class should only be read as a reference.
|
||||
VectorView(const VectorView &) = delete;
|
||||
void operator=(const VectorView &) = delete;
|
||||
|
||||
protected:
|
||||
VectorView() = default;
|
||||
T *ptr = nullptr;
|
||||
size_t buffer_size = 0;
|
||||
};
|
||||
|
||||
// Simple vector which supports up to N elements inline, without malloc/free.
|
||||
// We use a lot of throwaway vectors all over the place which triggers allocations.
|
||||
// This class only implements the subset of std::vector we need in SPIRV-Cross.
|
||||
// It is *NOT* a drop-in replacement in general projects.
|
||||
template <typename T, size_t N = 8>
|
||||
class SmallVector : public VectorView<T>
|
||||
{
|
||||
public:
|
||||
SmallVector() SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
this->ptr = stack_storage.data();
|
||||
buffer_capacity = N;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
SmallVector(const U *arg_list_begin, const U *arg_list_end) SPIRV_CROSS_NOEXCEPT : SmallVector()
|
||||
{
|
||||
auto count = size_t(arg_list_end - arg_list_begin);
|
||||
reserve(count);
|
||||
for (size_t i = 0; i < count; i++, arg_list_begin++)
|
||||
new (&this->ptr[i]) T(*arg_list_begin);
|
||||
this->buffer_size = count;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
SmallVector(std::initializer_list<U> init) SPIRV_CROSS_NOEXCEPT : SmallVector(init.begin(), init.end())
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U, size_t M>
|
||||
explicit SmallVector(const U (&init)[M]) SPIRV_CROSS_NOEXCEPT : SmallVector(init, init + M)
|
||||
{
|
||||
}
|
||||
|
||||
SmallVector(SmallVector &&other) SPIRV_CROSS_NOEXCEPT : SmallVector()
|
||||
{
|
||||
*this = std::move(other);
|
||||
}
|
||||
|
||||
SmallVector &operator=(SmallVector &&other) SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
clear();
|
||||
if (other.ptr != other.stack_storage.data())
|
||||
{
|
||||
// Pilfer allocated pointer.
|
||||
if (this->ptr != stack_storage.data())
|
||||
free(this->ptr);
|
||||
this->ptr = other.ptr;
|
||||
this->buffer_size = other.buffer_size;
|
||||
buffer_capacity = other.buffer_capacity;
|
||||
other.ptr = nullptr;
|
||||
other.buffer_size = 0;
|
||||
other.buffer_capacity = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Need to move the stack contents individually.
|
||||
reserve(other.buffer_size);
|
||||
for (size_t i = 0; i < other.buffer_size; i++)
|
||||
{
|
||||
new (&this->ptr[i]) T(std::move(other.ptr[i]));
|
||||
other.ptr[i].~T();
|
||||
}
|
||||
this->buffer_size = other.buffer_size;
|
||||
other.buffer_size = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
SmallVector(const SmallVector &other) SPIRV_CROSS_NOEXCEPT : SmallVector()
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
SmallVector &operator=(const SmallVector &other) SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
clear();
|
||||
reserve(other.buffer_size);
|
||||
for (size_t i = 0; i < other.buffer_size; i++)
|
||||
new (&this->ptr[i]) T(other.ptr[i]);
|
||||
this->buffer_size = other.buffer_size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit SmallVector(size_t count) SPIRV_CROSS_NOEXCEPT : SmallVector()
|
||||
{
|
||||
resize(count);
|
||||
}
|
||||
|
||||
~SmallVector()
|
||||
{
|
||||
clear();
|
||||
if (this->ptr != stack_storage.data())
|
||||
free(this->ptr);
|
||||
}
|
||||
|
||||
void clear() SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
for (size_t i = 0; i < this->buffer_size; i++)
|
||||
this->ptr[i].~T();
|
||||
this->buffer_size = 0;
|
||||
}
|
||||
|
||||
void push_back(const T &t) SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
reserve(this->buffer_size + 1);
|
||||
new (&this->ptr[this->buffer_size]) T(t);
|
||||
this->buffer_size++;
|
||||
}
|
||||
|
||||
void push_back(T &&t) SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
reserve(this->buffer_size + 1);
|
||||
new (&this->ptr[this->buffer_size]) T(std::move(t));
|
||||
this->buffer_size++;
|
||||
}
|
||||
|
||||
void pop_back() SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
// Work around false positive warning on GCC 8.3.
|
||||
// Calling pop_back on empty vector is undefined.
|
||||
if (!this->empty())
|
||||
resize(this->buffer_size - 1);
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
void emplace_back(Ts &&... ts) SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
reserve(this->buffer_size + 1);
|
||||
new (&this->ptr[this->buffer_size]) T(std::forward<Ts>(ts)...);
|
||||
this->buffer_size++;
|
||||
}
|
||||
|
||||
void reserve(size_t count) SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
if ((count > (std::numeric_limits<size_t>::max)() / sizeof(T)) ||
|
||||
(count > (std::numeric_limits<size_t>::max)() / 2))
|
||||
{
|
||||
// Only way this should ever happen is with garbage input, terminate.
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
if (count > buffer_capacity)
|
||||
{
|
||||
size_t target_capacity = buffer_capacity;
|
||||
if (target_capacity == 0)
|
||||
target_capacity = 1;
|
||||
|
||||
// Weird parens works around macro issues on Windows if NOMINMAX is not used.
|
||||
target_capacity = (std::max)(target_capacity, N);
|
||||
|
||||
// Need to ensure there is a POT value of target capacity which is larger than count,
|
||||
// otherwise this will overflow.
|
||||
while (target_capacity < count)
|
||||
target_capacity <<= 1u;
|
||||
|
||||
T *new_buffer =
|
||||
target_capacity > N ? static_cast<T *>(malloc(target_capacity * sizeof(T))) : stack_storage.data();
|
||||
|
||||
// If we actually fail this malloc, we are hosed anyways, there is no reason to attempt recovery.
|
||||
if (!new_buffer)
|
||||
std::terminate();
|
||||
|
||||
// In case for some reason two allocations both come from same stack.
|
||||
if (new_buffer != this->ptr)
|
||||
{
|
||||
// We don't deal with types which can throw in move constructor.
|
||||
for (size_t i = 0; i < this->buffer_size; i++)
|
||||
{
|
||||
new (&new_buffer[i]) T(std::move(this->ptr[i]));
|
||||
this->ptr[i].~T();
|
||||
}
|
||||
}
|
||||
|
||||
if (this->ptr != stack_storage.data())
|
||||
free(this->ptr);
|
||||
this->ptr = new_buffer;
|
||||
buffer_capacity = target_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
void insert(T *itr, const T *insert_begin, const T *insert_end) SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
auto count = size_t(insert_end - insert_begin);
|
||||
if (itr == this->end())
|
||||
{
|
||||
reserve(this->buffer_size + count);
|
||||
for (size_t i = 0; i < count; i++, insert_begin++)
|
||||
new (&this->ptr[this->buffer_size + i]) T(*insert_begin);
|
||||
this->buffer_size += count;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->buffer_size + count > buffer_capacity)
|
||||
{
|
||||
auto target_capacity = this->buffer_size + count;
|
||||
if (target_capacity == 0)
|
||||
target_capacity = 1;
|
||||
if (target_capacity < N)
|
||||
target_capacity = N;
|
||||
|
||||
while (target_capacity < count)
|
||||
target_capacity <<= 1u;
|
||||
|
||||
// Need to allocate new buffer. Move everything to a new buffer.
|
||||
T *new_buffer =
|
||||
target_capacity > N ? static_cast<T *>(malloc(target_capacity * sizeof(T))) : stack_storage.data();
|
||||
|
||||
// If we actually fail this malloc, we are hosed anyways, there is no reason to attempt recovery.
|
||||
if (!new_buffer)
|
||||
std::terminate();
|
||||
|
||||
// First, move elements from source buffer to new buffer.
|
||||
// We don't deal with types which can throw in move constructor.
|
||||
auto *target_itr = new_buffer;
|
||||
auto *original_source_itr = this->begin();
|
||||
|
||||
if (new_buffer != this->ptr)
|
||||
{
|
||||
while (original_source_itr != itr)
|
||||
{
|
||||
new (target_itr) T(std::move(*original_source_itr));
|
||||
original_source_itr->~T();
|
||||
++original_source_itr;
|
||||
++target_itr;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy-construct new elements.
|
||||
for (auto *source_itr = insert_begin; source_itr != insert_end; ++source_itr, ++target_itr)
|
||||
new (target_itr) T(*source_itr);
|
||||
|
||||
// Move over the other half.
|
||||
if (new_buffer != this->ptr || insert_begin != insert_end)
|
||||
{
|
||||
while (original_source_itr != this->end())
|
||||
{
|
||||
new (target_itr) T(std::move(*original_source_itr));
|
||||
original_source_itr->~T();
|
||||
++original_source_itr;
|
||||
++target_itr;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->ptr != stack_storage.data())
|
||||
free(this->ptr);
|
||||
this->ptr = new_buffer;
|
||||
buffer_capacity = target_capacity;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move in place, need to be a bit careful about which elements are constructed and which are not.
|
||||
// Move the end and construct the new elements.
|
||||
auto *target_itr = this->end() + count;
|
||||
auto *source_itr = this->end();
|
||||
while (target_itr != this->end() && source_itr != itr)
|
||||
{
|
||||
--target_itr;
|
||||
--source_itr;
|
||||
new (target_itr) T(std::move(*source_itr));
|
||||
}
|
||||
|
||||
// For already constructed elements we can move-assign.
|
||||
std::move_backward(itr, source_itr, target_itr);
|
||||
|
||||
// For the inserts which go to already constructed elements, we can do a plain copy.
|
||||
while (itr != this->end() && insert_begin != insert_end)
|
||||
*itr++ = *insert_begin++;
|
||||
|
||||
// For inserts into newly allocated memory, we must copy-construct instead.
|
||||
while (insert_begin != insert_end)
|
||||
{
|
||||
new (itr) T(*insert_begin);
|
||||
++itr;
|
||||
++insert_begin;
|
||||
}
|
||||
}
|
||||
|
||||
this->buffer_size += count;
|
||||
}
|
||||
}
|
||||
|
||||
void insert(T *itr, const T &value) SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
insert(itr, &value, &value + 1);
|
||||
}
|
||||
|
||||
T *erase(T *itr) SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
std::move(itr + 1, this->end(), itr);
|
||||
this->ptr[--this->buffer_size].~T();
|
||||
return itr;
|
||||
}
|
||||
|
||||
void erase(T *start_erase, T *end_erase) SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
if (end_erase == this->end())
|
||||
{
|
||||
resize(size_t(start_erase - this->begin()));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto new_size = this->buffer_size - (end_erase - start_erase);
|
||||
std::move(end_erase, this->end(), start_erase);
|
||||
resize(new_size);
|
||||
}
|
||||
}
|
||||
|
||||
void resize(size_t new_size) SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
if (new_size < this->buffer_size)
|
||||
{
|
||||
for (size_t i = new_size; i < this->buffer_size; i++)
|
||||
this->ptr[i].~T();
|
||||
}
|
||||
else if (new_size > this->buffer_size)
|
||||
{
|
||||
reserve(new_size);
|
||||
for (size_t i = this->buffer_size; i < new_size; i++)
|
||||
new (&this->ptr[i]) T();
|
||||
}
|
||||
|
||||
this->buffer_size = new_size;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t buffer_capacity = 0;
|
||||
AlignedBuffer<T, N> stack_storage;
|
||||
};
|
||||
|
||||
// A vector without stack storage.
|
||||
// Could also be a typedef-ed to std::vector,
|
||||
// but might as well use the one we have.
|
||||
template <typename T>
|
||||
using Vector = SmallVector<T, 0>;
|
||||
|
||||
#else // SPIRV_CROSS_FORCE_STL_TYPES
|
||||
|
||||
template <typename T, size_t N = 8>
|
||||
using SmallVector = std::vector<T>;
|
||||
template <typename T>
|
||||
using Vector = std::vector<T>;
|
||||
template <typename T>
|
||||
using VectorView = std::vector<T>;
|
||||
|
||||
#endif // SPIRV_CROSS_FORCE_STL_TYPES
|
||||
|
||||
// An object pool which we use for allocating IVariant-derived objects.
|
||||
// We know we are going to allocate a bunch of objects of each type,
|
||||
// so amortize the mallocs.
|
||||
class ObjectPoolBase
|
||||
{
|
||||
public:
|
||||
virtual ~ObjectPoolBase() = default;
|
||||
virtual void deallocate_opaque(void *ptr) = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ObjectPool : public ObjectPoolBase
|
||||
{
|
||||
public:
|
||||
explicit ObjectPool(unsigned start_object_count_ = 16)
|
||||
: start_object_count(start_object_count_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename... P>
|
||||
T *allocate(P &&... p)
|
||||
{
|
||||
if (vacants.empty())
|
||||
{
|
||||
unsigned num_objects = start_object_count << memory.size();
|
||||
T *ptr = static_cast<T *>(malloc(num_objects * sizeof(T)));
|
||||
if (!ptr)
|
||||
return nullptr;
|
||||
|
||||
for (unsigned i = 0; i < num_objects; i++)
|
||||
vacants.push_back(&ptr[i]);
|
||||
|
||||
memory.emplace_back(ptr);
|
||||
}
|
||||
|
||||
T *ptr = vacants.back();
|
||||
vacants.pop_back();
|
||||
new (ptr) T(std::forward<P>(p)...);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void deallocate(T *ptr)
|
||||
{
|
||||
ptr->~T();
|
||||
vacants.push_back(ptr);
|
||||
}
|
||||
|
||||
void deallocate_opaque(void *ptr) override
|
||||
{
|
||||
deallocate(static_cast<T *>(ptr));
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
vacants.clear();
|
||||
memory.clear();
|
||||
}
|
||||
|
||||
protected:
|
||||
Vector<T *> vacants;
|
||||
|
||||
struct MallocDeleter
|
||||
{
|
||||
void operator()(T *ptr)
|
||||
{
|
||||
::free(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
SmallVector<std::unique_ptr<T, MallocDeleter>> memory;
|
||||
unsigned start_object_count;
|
||||
};
|
||||
|
||||
template <size_t StackSize = 4096, size_t BlockSize = 4096>
|
||||
class StringStream
|
||||
{
|
||||
public:
|
||||
StringStream()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
~StringStream()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
// Disable copies and moves. Makes it easier to implement, and we don't need it.
|
||||
StringStream(const StringStream &) = delete;
|
||||
void operator=(const StringStream &) = delete;
|
||||
|
||||
template <typename T, typename std::enable_if<!std::is_floating_point<T>::value, int>::type = 0>
|
||||
StringStream &operator<<(const T &t)
|
||||
{
|
||||
auto s = std::to_string(t);
|
||||
append(s.data(), s.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Only overload this to make float/double conversions ambiguous.
|
||||
StringStream &operator<<(uint32_t v)
|
||||
{
|
||||
auto s = std::to_string(v);
|
||||
append(s.data(), s.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream &operator<<(char c)
|
||||
{
|
||||
append(&c, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream &operator<<(const std::string &s)
|
||||
{
|
||||
append(s.data(), s.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream &operator<<(const char *s)
|
||||
{
|
||||
append(s, strlen(s));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
StringStream &operator<<(const char (&s)[N])
|
||||
{
|
||||
append(s, strlen(s));
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string str() const
|
||||
{
|
||||
std::string ret;
|
||||
size_t target_size = 0;
|
||||
for (auto &saved : saved_buffers)
|
||||
target_size += saved.offset;
|
||||
target_size += current_buffer.offset;
|
||||
ret.reserve(target_size);
|
||||
|
||||
for (auto &saved : saved_buffers)
|
||||
ret.insert(ret.end(), saved.buffer, saved.buffer + saved.offset);
|
||||
ret.insert(ret.end(), current_buffer.buffer, current_buffer.buffer + current_buffer.offset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
for (auto &saved : saved_buffers)
|
||||
if (saved.buffer != stack_buffer)
|
||||
free(saved.buffer);
|
||||
if (current_buffer.buffer != stack_buffer)
|
||||
free(current_buffer.buffer);
|
||||
|
||||
saved_buffers.clear();
|
||||
current_buffer.buffer = stack_buffer;
|
||||
current_buffer.offset = 0;
|
||||
current_buffer.size = sizeof(stack_buffer);
|
||||
}
|
||||
|
||||
private:
|
||||
struct Buffer
|
||||
{
|
||||
char *buffer = nullptr;
|
||||
size_t offset = 0;
|
||||
size_t size = 0;
|
||||
};
|
||||
Buffer current_buffer;
|
||||
char stack_buffer[StackSize];
|
||||
SmallVector<Buffer> saved_buffers;
|
||||
|
||||
void append(const char *s, size_t len)
|
||||
{
|
||||
size_t avail = current_buffer.size - current_buffer.offset;
|
||||
if (avail < len)
|
||||
{
|
||||
if (avail > 0)
|
||||
{
|
||||
memcpy(current_buffer.buffer + current_buffer.offset, s, avail);
|
||||
s += avail;
|
||||
len -= avail;
|
||||
current_buffer.offset += avail;
|
||||
}
|
||||
|
||||
saved_buffers.push_back(current_buffer);
|
||||
size_t target_size = len > BlockSize ? len : BlockSize;
|
||||
current_buffer.buffer = static_cast<char *>(malloc(target_size));
|
||||
if (!current_buffer.buffer)
|
||||
SPIRV_CROSS_THROW("Out of memory.");
|
||||
|
||||
memcpy(current_buffer.buffer, s, len);
|
||||
current_buffer.offset = len;
|
||||
current_buffer.size = target_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(current_buffer.buffer + current_buffer.offset, s, len);
|
||||
current_buffer.offset += len;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
#endif
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2015-2021 Arm Limited
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* At your option, you may choose to accept this material under either:
|
||||
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
|
||||
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
|
||||
*/
|
||||
|
||||
#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
|
256
dep/spirv-cross/include/spirv-cross/spirv_cross_parsed_ir.hpp
Normal file
256
dep/spirv-cross/include/spirv-cross/spirv_cross_parsed_ir.hpp
Normal file
@ -0,0 +1,256 @@
|
||||
/*
|
||||
* Copyright 2018-2021 Arm Limited
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* At your option, you may choose to accept this material under either:
|
||||
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
|
||||
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
|
||||
*/
|
||||
|
||||
#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 undef or of struct type, and struct array sizes can use specialization constants.
|
||||
SmallVector<ID> ids_for_constant_undef_or_type;
|
||||
SmallVector<ID> ids_for_constant_or_variable;
|
||||
|
||||
// We need to keep track of the width the Ops that contains a type for the
|
||||
// OpSwitch instruction, since this one doesn't contains the type in the
|
||||
// instruction itself. And in some case we need to cast the condition to
|
||||
// wider types. We only need the width to do the branch fixup since the
|
||||
// type check itself can be done at runtime
|
||||
std::unordered_map<ID, uint32_t> load_type_width;
|
||||
|
||||
// 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;
|
||||
Bitset get_buffer_block_type_flags(const SPIRType &type) 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);
|
||||
|
||||
void fixup_reserved_names();
|
||||
|
||||
static void sanitize_underscores(std::string &str);
|
||||
static void sanitize_identifier(std::string &str, bool member, bool allow_reserved_prefixes);
|
||||
static bool is_globally_reserved_identifier(std::string &str, bool allow_reserved_prefixes);
|
||||
|
||||
uint32_t get_spirv_version() const;
|
||||
|
||||
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;
|
||||
|
||||
std::unordered_set<uint32_t> meta_needing_name_fixup;
|
||||
};
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
#endif
|
37
dep/spirv-cross/include/spirv-cross/spirv_cross_util.hpp
Normal file
37
dep/spirv-cross/include/spirv-cross/spirv_cross_util.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2015-2021 Arm Limited
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* At your option, you may choose to accept this material under either:
|
||||
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
|
||||
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
|
||||
*/
|
||||
|
||||
#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
|
1033
dep/spirv-cross/include/spirv-cross/spirv_glsl.hpp
Normal file
1033
dep/spirv-cross/include/spirv-cross/spirv_glsl.hpp
Normal file
File diff suppressed because it is too large
Load Diff
407
dep/spirv-cross/include/spirv-cross/spirv_hlsl.hpp
Normal file
407
dep/spirv-cross/include/spirv-cross/spirv_hlsl.hpp
Normal file
@ -0,0 +1,407 @@
|
||||
/*
|
||||
* Copyright 2016-2021 Robert Konrad
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* At your option, you may choose to accept this material under either:
|
||||
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
|
||||
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
|
||||
*/
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
enum HLSLAuxBinding
|
||||
{
|
||||
HLSL_AUX_BINDING_BASE_VERTEX_INSTANCE = 0
|
||||
};
|
||||
|
||||
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 in SM 4.0+, and ignores it, as PointSize is not supported in SM 4+.
|
||||
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;
|
||||
|
||||
// If matrices are used as IO variables, flatten the attribute declaration to use
|
||||
// TEXCOORD{N,N+1,N+2,...} rather than TEXCOORDN_{0,1,2,3}.
|
||||
// If add_vertex_attribute_remap is used and this feature is used,
|
||||
// the semantic name will be queried once per active location.
|
||||
bool flatten_matrix_vertex_input_semantics = false;
|
||||
|
||||
// Rather than emitting main() for the entry point, use the name in SPIR-V.
|
||||
bool use_entry_point_name = false;
|
||||
};
|
||||
|
||||
explicit CompilerHLSL(std::vector<uint32_t> spirv_)
|
||||
: 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);
|
||||
|
||||
// By default, these magic buffers are not assigned a specific binding.
|
||||
void set_hlsl_aux_buffer_binding(HLSLAuxBinding binding, uint32_t register_index, uint32_t register_space);
|
||||
void unset_hlsl_aux_buffer_binding(HLSLAuxBinding binding);
|
||||
bool is_hlsl_aux_buffer_binding_used(HLSLAuxBinding binding) const;
|
||||
|
||||
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 emit_interface_block_globally(const SPIRVariable &type);
|
||||
void emit_interface_block_in_struct(const SPIRVariable &var, std::unordered_set<uint32_t> &active_locations);
|
||||
void emit_interface_block_member_in_struct(const SPIRVariable &var, uint32_t member_index, uint32_t location,
|
||||
std::unordered_set<uint32_t> &active_locations);
|
||||
void emit_builtin_inputs_in_struct();
|
||||
void emit_builtin_outputs_in_struct();
|
||||
void emit_builtin_primitive_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);
|
||||
std::string to_initializer_expression(const SPIRVariable &var) override;
|
||||
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;
|
||||
void emit_rayquery_function(const char *commited, const char *candidate, const uint32_t *ops);
|
||||
void emit_mesh_tasks(SPIRBlock &block) 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
|
||||
};
|
||||
|
||||
void analyze_meshlet_writes();
|
||||
void analyze_meshlet_writes(uint32_t func_id, uint32_t id_per_vertex, uint32_t id_per_primitive,
|
||||
std::unordered_set<uint32_t> &processed_func_ids);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t register_index = 0;
|
||||
uint32_t register_space = 0;
|
||||
bool explicit_binding = false;
|
||||
bool used = false;
|
||||
} base_vertex_info;
|
||||
|
||||
// Returns true for BuiltInSampleMask because gl_SampleMask[] is an array in SPIR-V, but SV_Coverage is a scalar in HLSL.
|
||||
bool builtin_translates_to_nonarray(spv::BuiltIn builtin) const override;
|
||||
|
||||
std::vector<TypeID> composite_selection_workaround_types;
|
||||
|
||||
std::string get_inner_entry_point_name() const;
|
||||
};
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
#endif
|
1297
dep/spirv-cross/include/spirv-cross/spirv_msl.hpp
Normal file
1297
dep/spirv-cross/include/spirv-cross/spirv_msl.hpp
Normal file
File diff suppressed because it is too large
Load Diff
103
dep/spirv-cross/include/spirv-cross/spirv_parser.hpp
Normal file
103
dep/spirv-cross/include/spirv-cross/spirv_parser.hpp
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2018-2021 Arm Limited
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* At your option, you may choose to accept this material under either:
|
||||
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
|
||||
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
|
||||
*/
|
||||
|
||||
#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;
|
||||
// For workarounds.
|
||||
bool ignore_trailing_block_opcodes = false;
|
||||
|
||||
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
|
91
dep/spirv-cross/include/spirv-cross/spirv_reflect.hpp
Normal file
91
dep/spirv-cross/include/spirv-cross/spirv_reflect.hpp
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2018-2021 Bradley Austin Davis
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* At your option, you may choose to accept this material under either:
|
||||
* 1. The Apache License, Version 2.0, found at <http://www.apache.org/licenses/LICENSE-2.0>, or
|
||||
* 2. The MIT License, found at <http://opensource.org/licenses/MIT>.
|
||||
*/
|
||||
|
||||
#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
|
Reference in New Issue
Block a user