mirror of
https://github.com/KhronosGroup/SPIRV-Cross.git
synced 2024-11-09 22:00:05 +00:00
Reduce pressure on global allocation.
- Replace ostringstream with custom implementation. ~30% performance uplift on vector-shuffle-oom test. Allocations are measurably reduced in Valgrind. - Replace std::vector with SmallVector. Classic malloc optimization, small vectors are backed by inline data. ~ 7-8% gain on vector-shuffle-oom on GCC 8 on Linux. - Use an object pool for IVariant type. We generally allocate a lot of SPIR* objects. We can amortize these allocations neatly by pooling them. - ~15% overall uplift on ./test_shaders.py --iterations 10000 shaders/.
This commit is contained in:
parent
c60b9a1e96
commit
a489ba7fd1
36
main.cpp
36
main.cpp
@ -186,7 +186,7 @@ struct CLIParser
|
||||
bool ended_state = false;
|
||||
};
|
||||
|
||||
static vector<uint32_t> read_spirv_file(const char *path)
|
||||
static SmallVector<uint32_t> read_spirv_file(const char *path)
|
||||
{
|
||||
FILE *file = fopen(path, "rb");
|
||||
if (!file)
|
||||
@ -199,7 +199,7 @@ static vector<uint32_t> read_spirv_file(const char *path)
|
||||
long len = ftell(file) / sizeof(uint32_t);
|
||||
rewind(file);
|
||||
|
||||
vector<uint32_t> spirv(len);
|
||||
SmallVector<uint32_t> spirv(len);
|
||||
if (fread(spirv.data(), sizeof(uint32_t), len, file) != size_t(len))
|
||||
spirv.clear();
|
||||
|
||||
@ -221,7 +221,7 @@ static bool write_string_to_file(const char *path, const char *string)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void print_resources(const Compiler &compiler, const char *tag, const vector<Resource> &resources)
|
||||
static void print_resources(const Compiler &compiler, const char *tag, const SmallVector<Resource> &resources)
|
||||
{
|
||||
fprintf(stderr, "%s\n", tag);
|
||||
fprintf(stderr, "=============\n\n");
|
||||
@ -411,7 +411,7 @@ static void print_resources(const Compiler &compiler, const ShaderResources &res
|
||||
print_resources(compiler, "acceleration structures", res.acceleration_structures);
|
||||
}
|
||||
|
||||
static void print_push_constant_resources(const Compiler &compiler, const vector<Resource> &res)
|
||||
static void print_push_constant_resources(const Compiler &compiler, const SmallVector<Resource> &res)
|
||||
{
|
||||
for (auto &block : res)
|
||||
{
|
||||
@ -510,14 +510,14 @@ struct CLIArguments
|
||||
bool msl_domain_lower_left = false;
|
||||
bool msl_argument_buffers = false;
|
||||
bool glsl_emit_push_constant_as_ubo = false;
|
||||
vector<uint32_t> msl_discrete_descriptor_sets;
|
||||
vector<PLSArg> pls_in;
|
||||
vector<PLSArg> pls_out;
|
||||
vector<Remap> remaps;
|
||||
vector<string> extensions;
|
||||
vector<VariableTypeRemap> variable_type_remaps;
|
||||
vector<InterfaceVariableRename> interface_variable_renames;
|
||||
vector<HLSLVertexAttributeRemap> hlsl_attr_remap;
|
||||
SmallVector<uint32_t> msl_discrete_descriptor_sets;
|
||||
SmallVector<PLSArg> pls_in;
|
||||
SmallVector<PLSArg> pls_out;
|
||||
SmallVector<Remap> remaps;
|
||||
SmallVector<string> extensions;
|
||||
SmallVector<VariableTypeRemap> variable_type_remaps;
|
||||
SmallVector<InterfaceVariableRename> interface_variable_renames;
|
||||
SmallVector<HLSLVertexAttributeRemap> hlsl_attr_remap;
|
||||
string entry;
|
||||
string entry_stage;
|
||||
|
||||
@ -527,7 +527,7 @@ struct CLIArguments
|
||||
string new_name;
|
||||
ExecutionModel execution_model;
|
||||
};
|
||||
vector<Rename> entry_point_rename;
|
||||
SmallVector<Rename> entry_point_rename;
|
||||
|
||||
uint32_t iterations = 1;
|
||||
bool cpp = false;
|
||||
@ -595,7 +595,7 @@ static void print_help()
|
||||
"\n");
|
||||
}
|
||||
|
||||
static bool remap_generic(Compiler &compiler, const vector<Resource> &resources, const Remap &remap)
|
||||
static bool remap_generic(Compiler &compiler, const SmallVector<Resource> &resources, const Remap &remap)
|
||||
{
|
||||
auto itr =
|
||||
find_if(begin(resources), end(resources), [&remap](const Resource &res) { return res.name == remap.src_name; });
|
||||
@ -611,10 +611,10 @@ static bool remap_generic(Compiler &compiler, const vector<Resource> &resources,
|
||||
return false;
|
||||
}
|
||||
|
||||
static vector<PlsRemap> remap_pls(const vector<PLSArg> &pls_variables, const vector<Resource> &resources,
|
||||
const vector<Resource> *secondary_resources)
|
||||
static SmallVector<PlsRemap> remap_pls(const SmallVector<PLSArg> &pls_variables, const SmallVector<Resource> &resources,
|
||||
const SmallVector<Resource> *secondary_resources)
|
||||
{
|
||||
vector<PlsRemap> ret;
|
||||
SmallVector<PlsRemap> ret;
|
||||
|
||||
for (auto &pls : pls_variables)
|
||||
{
|
||||
@ -697,7 +697,7 @@ static ExecutionModel stage_to_execution_model(const std::string &stage)
|
||||
SPIRV_CROSS_THROW("Invalid stage.");
|
||||
}
|
||||
|
||||
static string compile_iteration(const CLIArguments &args, vector<uint32_t> spirv_file)
|
||||
static string compile_iteration(const CLIArguments &args, SmallVector<uint32_t> spirv_file)
|
||||
{
|
||||
Parser spirv_parser(move(spirv_file));
|
||||
spirv_parser.parse();
|
||||
|
@ -143,7 +143,7 @@ void CFG::build_post_order_visit_order()
|
||||
|
||||
void CFG::add_branch(uint32_t from, uint32_t to)
|
||||
{
|
||||
const auto add_unique = [](vector<uint32_t> &l, uint32_t value) {
|
||||
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);
|
||||
@ -223,4 +223,4 @@ void DominatorBuilder::lift_continue_block_dominator()
|
||||
if (back_edge_dominator)
|
||||
dominator = cfg.get_function().entry_block;
|
||||
}
|
||||
} // namespace spirv_cross
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
@ -63,7 +63,7 @@ public:
|
||||
|
||||
uint32_t find_common_dominator(uint32_t a, uint32_t b) const;
|
||||
|
||||
const std::vector<uint32_t> &get_preceding_edges(uint32_t block) const
|
||||
const SmallVector<uint32_t> &get_preceding_edges(uint32_t block) const
|
||||
{
|
||||
auto itr = preceding_edges.find(block);
|
||||
if (itr != std::end(preceding_edges))
|
||||
@ -72,7 +72,7 @@ public:
|
||||
return empty_vector;
|
||||
}
|
||||
|
||||
const std::vector<uint32_t> &get_succeeding_edges(uint32_t block) const
|
||||
const SmallVector<uint32_t> &get_succeeding_edges(uint32_t block) const
|
||||
{
|
||||
auto itr = succeeding_edges.find(block);
|
||||
if (itr != std::end(succeeding_edges))
|
||||
@ -111,12 +111,12 @@ private:
|
||||
|
||||
Compiler &compiler;
|
||||
const SPIRFunction &func;
|
||||
std::unordered_map<uint32_t, std::vector<uint32_t>> preceding_edges;
|
||||
std::unordered_map<uint32_t, std::vector<uint32_t>> succeeding_edges;
|
||||
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;
|
||||
std::vector<uint32_t> post_order;
|
||||
std::vector<uint32_t> empty_vector;
|
||||
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();
|
||||
@ -144,6 +144,6 @@ private:
|
||||
const CFG &cfg;
|
||||
uint32_t dominator = 0;
|
||||
};
|
||||
} // namespace spirv_cross
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
697
spirv_common.hpp
697
spirv_common.hpp
@ -20,20 +20,19 @@
|
||||
#include "spirv.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// A bit crude, but allows projects which embed SPIRV-Cross statically to
|
||||
// effectively hide all the symbols from other projects.
|
||||
@ -105,16 +104,543 @@ public:
|
||||
#define SPIRV_CROSS_DEPRECATED(reason)
|
||||
#endif
|
||||
|
||||
// std::aligned_storage does not support size == 0, so roll our own.
|
||||
template <typename T, size_t N>
|
||||
class AlignedBuffer
|
||||
{
|
||||
public:
|
||||
T *data()
|
||||
{
|
||||
return reinterpret_cast<T *>(aligned_char);
|
||||
}
|
||||
|
||||
private:
|
||||
alignas(T) char aligned_char[sizeof(T) * N];
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
return ptr[i];
|
||||
}
|
||||
|
||||
const T &operator[](size_t i) const
|
||||
{
|
||||
return ptr[i];
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return buffer_size == 0;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return buffer_size;
|
||||
}
|
||||
|
||||
T *data()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
const T *data() const
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
T *begin()
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
T *end()
|
||||
{
|
||||
return ptr + buffer_size;
|
||||
}
|
||||
|
||||
const T *begin() const
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
const T *end() const
|
||||
{
|
||||
return ptr + buffer_size;
|
||||
}
|
||||
|
||||
T &front()
|
||||
{
|
||||
return ptr[0];
|
||||
}
|
||||
|
||||
const T &front() const
|
||||
{
|
||||
return ptr[0];
|
||||
}
|
||||
|
||||
T &back()
|
||||
{
|
||||
return ptr[buffer_size - 1];
|
||||
}
|
||||
|
||||
const T &back() const
|
||||
{
|
||||
return ptr[buffer_size - 1];
|
||||
}
|
||||
|
||||
// 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.
|
||||
template <typename T, size_t N = 8>
|
||||
class SmallVector : public VectorView<T>
|
||||
{
|
||||
public:
|
||||
SmallVector()
|
||||
{
|
||||
this->ptr = stack_storage.data();
|
||||
buffer_capacity = N;
|
||||
}
|
||||
|
||||
SmallVector(const T *arg_list_begin, const T *arg_list_end)
|
||||
: 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;
|
||||
}
|
||||
|
||||
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)
|
||||
: SmallVector()
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
SmallVector &operator=(const SmallVector &other)
|
||||
{
|
||||
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)
|
||||
: SmallVector()
|
||||
{
|
||||
resize(count);
|
||||
}
|
||||
|
||||
~SmallVector()
|
||||
{
|
||||
clear();
|
||||
if (this->ptr != stack_storage.data())
|
||||
free(this->ptr);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
for (size_t i = 0; i < this->buffer_size; i++)
|
||||
this->ptr[i].~T();
|
||||
this->buffer_size = 0;
|
||||
}
|
||||
|
||||
void push_back(const T &t)
|
||||
{
|
||||
reserve(this->buffer_size + 1);
|
||||
new (&this->ptr[this->buffer_size]) T(t);
|
||||
this->buffer_size++;
|
||||
}
|
||||
|
||||
void push_back(T &&t)
|
||||
{
|
||||
reserve(this->buffer_size + 1);
|
||||
new (&this->ptr[this->buffer_size]) T(std::move(t));
|
||||
this->buffer_size++;
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
resize(this->buffer_size - 1);
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
void emplace_back(Ts &&... ts)
|
||||
{
|
||||
reserve(this->buffer_size + 1);
|
||||
new (&this->ptr[this->buffer_size]) T(std::forward<Ts>(ts)...);
|
||||
this->buffer_size++;
|
||||
}
|
||||
|
||||
void reserve(size_t count)
|
||||
{
|
||||
if (count > buffer_capacity)
|
||||
{
|
||||
size_t target_capacity = buffer_capacity;
|
||||
if (target_capacity == 0)
|
||||
target_capacity = 1;
|
||||
if (target_capacity < N)
|
||||
target_capacity = N;
|
||||
|
||||
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 (!new_buffer)
|
||||
SPIRV_CROSS_THROW("Out of memory.");
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (itr == this->end())
|
||||
{
|
||||
auto count = size_t(insert_end - insert_begin);
|
||||
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
|
||||
SPIRV_CROSS_THROW("Mid-insert not implemented.");
|
||||
}
|
||||
|
||||
T *erase(T *itr)
|
||||
{
|
||||
std::move(itr + 1, this->end(), itr);
|
||||
this->ptr[--this->buffer_size].~T();
|
||||
return itr;
|
||||
}
|
||||
|
||||
void erase(T *start_erase, T *end_erase)
|
||||
{
|
||||
if (end_erase != this->end())
|
||||
SPIRV_CROSS_THROW("Mid-erase not implemented.");
|
||||
resize(size_t(start_erase - this->begin()));
|
||||
}
|
||||
|
||||
void resize(size_t new_size)
|
||||
{
|
||||
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>;
|
||||
|
||||
// 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 free_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 free(T *ptr)
|
||||
{
|
||||
ptr->~T();
|
||||
vacants.push_back(ptr);
|
||||
}
|
||||
|
||||
void free_opaque(void *ptr) override
|
||||
{
|
||||
free(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 &str)
|
||||
{
|
||||
append(str.data(), str.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;
|
||||
size_t offset;
|
||||
size_t size;
|
||||
};
|
||||
Buffer current_buffer = {};
|
||||
char stack_buffer[StackSize];
|
||||
SmallVector<Buffer> saved_buffers;
|
||||
|
||||
void append(const char *str, 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, str, avail);
|
||||
str += 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, str, len);
|
||||
current_buffer.offset = len;
|
||||
current_buffer.size = target_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(current_buffer.buffer + current_buffer.offset, str, len);
|
||||
current_buffer.offset += len;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace inner
|
||||
{
|
||||
template <typename T>
|
||||
void join_helper(std::ostringstream &stream, T &&t)
|
||||
void join_helper(StringStream<> &stream, T &&t)
|
||||
{
|
||||
stream << std::forward<T>(t);
|
||||
}
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
void join_helper(std::ostringstream &stream, T &&t, Ts &&... ts)
|
||||
void join_helper(StringStream<> &stream, T &&t, Ts &&... ts)
|
||||
{
|
||||
stream << std::forward<T>(t);
|
||||
join_helper(stream, std::forward<Ts>(ts)...);
|
||||
@ -217,7 +743,7 @@ public:
|
||||
|
||||
// Need to enforce an order here for reproducible results,
|
||||
// but hitting this path should happen extremely rarely, so having this slow path is fine.
|
||||
std::vector<uint32_t> bits;
|
||||
SmallVector<uint32_t> bits;
|
||||
bits.reserve(higher.size());
|
||||
for (auto &v : higher)
|
||||
bits.push_back(v);
|
||||
@ -244,21 +770,21 @@ private:
|
||||
template <typename... Ts>
|
||||
std::string join(Ts &&... ts)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
StringStream<> stream;
|
||||
inner::join_helper(stream, std::forward<Ts>(ts)...);
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
inline std::string merge(const std::vector<std::string> &list)
|
||||
inline std::string merge(const SmallVector<std::string> &list)
|
||||
{
|
||||
std::string s;
|
||||
StringStream<> stream;
|
||||
for (auto &elem : list)
|
||||
{
|
||||
s += elem;
|
||||
stream << elem;
|
||||
if (&elem != &list.back())
|
||||
s += ", ";
|
||||
stream << ", ";
|
||||
}
|
||||
return s;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
// Make sure we don't accidentally call this with float or doubles with SFINAE.
|
||||
@ -340,15 +866,14 @@ struct Instruction
|
||||
struct IVariant
|
||||
{
|
||||
virtual ~IVariant() = default;
|
||||
virtual std::unique_ptr<IVariant> clone() = 0;
|
||||
|
||||
virtual IVariant *clone(ObjectPoolBase *pool) = 0;
|
||||
uint32_t self = 0;
|
||||
};
|
||||
|
||||
#define SPIRV_CROSS_DECLARE_CLONE(T) \
|
||||
std::unique_ptr<IVariant> clone() override \
|
||||
{ \
|
||||
return std::unique_ptr<IVariant>(new T(*this)); \
|
||||
#define SPIRV_CROSS_DECLARE_CLONE(T) \
|
||||
IVariant *clone(ObjectPoolBase *pool) override \
|
||||
{ \
|
||||
return static_cast<ObjectPool<T> *>(pool)->allocate(*this); \
|
||||
}
|
||||
|
||||
enum Types
|
||||
@ -421,7 +946,7 @@ struct SPIRConstantOp : IVariant
|
||||
}
|
||||
|
||||
spv::Op opcode;
|
||||
std::vector<uint32_t> arguments;
|
||||
SmallVector<uint32_t> arguments;
|
||||
uint32_t basetype;
|
||||
|
||||
SPIRV_CROSS_DECLARE_CLONE(SPIRConstantOp)
|
||||
@ -469,14 +994,14 @@ struct SPIRType : IVariant
|
||||
uint32_t columns = 1;
|
||||
|
||||
// Arrays, support array of arrays by having a vector of array sizes.
|
||||
std::vector<uint32_t> array;
|
||||
SmallVector<uint32_t> array;
|
||||
|
||||
// Array elements can be either specialization constants or specialization ops.
|
||||
// This array determines how to interpret the array size.
|
||||
// If an element is true, the element is a literal,
|
||||
// otherwise, it's an expression, which must be resolved on demand.
|
||||
// The actual size is not really known until runtime.
|
||||
std::vector<bool> array_size_literal;
|
||||
SmallVector<bool> array_size_literal;
|
||||
|
||||
// Pointers
|
||||
// Keep track of how many pointer layers we have.
|
||||
@ -485,7 +1010,7 @@ struct SPIRType : IVariant
|
||||
|
||||
spv::StorageClass storage = spv::StorageClassGeneric;
|
||||
|
||||
std::vector<uint32_t> member_types;
|
||||
SmallVector<uint32_t> member_types;
|
||||
|
||||
struct ImageType
|
||||
{
|
||||
@ -556,7 +1081,7 @@ struct SPIREntryPoint
|
||||
uint32_t self = 0;
|
||||
std::string name;
|
||||
std::string orig_name;
|
||||
std::vector<uint32_t> interface_variables;
|
||||
SmallVector<uint32_t> interface_variables;
|
||||
|
||||
Bitset flags;
|
||||
struct
|
||||
@ -610,11 +1135,11 @@ struct SPIRExpression : IVariant
|
||||
bool access_chain = false;
|
||||
|
||||
// A list of expressions which this expression depends on.
|
||||
std::vector<uint32_t> expression_dependencies;
|
||||
SmallVector<uint32_t> expression_dependencies;
|
||||
|
||||
// By reading this expression, we implicitly read these expressions as well.
|
||||
// Used by access chain Store and Load since we read multiple expressions in this case.
|
||||
std::vector<uint32_t> implied_read_expressions;
|
||||
SmallVector<uint32_t> implied_read_expressions;
|
||||
|
||||
SPIRV_CROSS_DECLARE_CLONE(SPIRExpression)
|
||||
};
|
||||
@ -632,7 +1157,7 @@ struct SPIRFunctionPrototype : IVariant
|
||||
}
|
||||
|
||||
uint32_t return_type;
|
||||
std::vector<uint32_t> parameter_types;
|
||||
SmallVector<uint32_t> parameter_types;
|
||||
|
||||
SPIRV_CROSS_DECLARE_CLONE(SPIRFunctionPrototype)
|
||||
};
|
||||
@ -716,7 +1241,7 @@ struct SPIRBlock : IVariant
|
||||
uint32_t false_block = 0;
|
||||
uint32_t default_block = 0;
|
||||
|
||||
std::vector<Instruction> ops;
|
||||
SmallVector<Instruction> ops;
|
||||
|
||||
struct Phi
|
||||
{
|
||||
@ -726,22 +1251,22 @@ struct SPIRBlock : IVariant
|
||||
};
|
||||
|
||||
// Before entering this block flush out local variables to magical "phi" variables.
|
||||
std::vector<Phi> phi_variables;
|
||||
SmallVector<Phi> phi_variables;
|
||||
|
||||
// Declare these temporaries before beginning the block.
|
||||
// Used for handling complex continue blocks which have side effects.
|
||||
std::vector<std::pair<uint32_t, uint32_t>> declare_temporary;
|
||||
SmallVector<std::pair<uint32_t, uint32_t>> declare_temporary;
|
||||
|
||||
// Declare these temporaries, but only conditionally if this block turns out to be
|
||||
// a complex loop header.
|
||||
std::vector<std::pair<uint32_t, uint32_t>> potential_declare_temporary;
|
||||
SmallVector<std::pair<uint32_t, uint32_t>> potential_declare_temporary;
|
||||
|
||||
struct Case
|
||||
{
|
||||
uint32_t value;
|
||||
uint32_t block;
|
||||
};
|
||||
std::vector<Case> cases;
|
||||
SmallVector<Case> cases;
|
||||
|
||||
// If we have tried to optimize code for this block but failed,
|
||||
// keep track of this.
|
||||
@ -759,17 +1284,17 @@ struct SPIRBlock : IVariant
|
||||
|
||||
// All access to these variables are dominated by this block,
|
||||
// so before branching anywhere we need to make sure that we declare these variables.
|
||||
std::vector<uint32_t> dominated_variables;
|
||||
SmallVector<uint32_t> dominated_variables;
|
||||
|
||||
// These are variables which should be declared in a for loop header, if we
|
||||
// fail to use a classic for-loop,
|
||||
// we remove these variables, and fall back to regular variables outside the loop.
|
||||
std::vector<uint32_t> loop_variables;
|
||||
SmallVector<uint32_t> loop_variables;
|
||||
|
||||
// Some expressions are control-flow dependent, i.e. any instruction which relies on derivatives or
|
||||
// sub-group-like operations.
|
||||
// Make sure that we only use these expressions in the original block.
|
||||
std::vector<uint32_t> invalidate_expressions;
|
||||
SmallVector<uint32_t> invalidate_expressions;
|
||||
|
||||
SPIRV_CROSS_DECLARE_CLONE(SPIRBlock)
|
||||
};
|
||||
@ -822,16 +1347,16 @@ struct SPIRFunction : IVariant
|
||||
|
||||
uint32_t return_type;
|
||||
uint32_t function_type;
|
||||
std::vector<Parameter> arguments;
|
||||
SmallVector<Parameter> arguments;
|
||||
|
||||
// Can be used by backends to add magic arguments.
|
||||
// Currently used by combined image/sampler implementation.
|
||||
|
||||
std::vector<Parameter> shadow_arguments;
|
||||
std::vector<uint32_t> local_variables;
|
||||
SmallVector<Parameter> shadow_arguments;
|
||||
SmallVector<uint32_t> local_variables;
|
||||
uint32_t entry_block = 0;
|
||||
std::vector<uint32_t> blocks;
|
||||
std::vector<CombinedImageSamplerParameter> combined_parameters;
|
||||
SmallVector<uint32_t> blocks;
|
||||
SmallVector<CombinedImageSamplerParameter> combined_parameters;
|
||||
|
||||
void add_local_variable(uint32_t id)
|
||||
{
|
||||
@ -847,17 +1372,19 @@ struct SPIRFunction : IVariant
|
||||
// Hooks to be run when the function returns.
|
||||
// Mostly used for lowering internal data structures onto flattened structures.
|
||||
// Need to defer this, because they might rely on things which change during compilation.
|
||||
std::vector<std::function<void()>> fixup_hooks_out;
|
||||
// Intentionally not a small vector, this one is rare, and std::function can be large.
|
||||
Vector<std::function<void()>> fixup_hooks_out;
|
||||
|
||||
// Hooks to be run when the function begins.
|
||||
// Mostly used for populating internal data structures from flattened structures.
|
||||
// Need to defer this, because they might rely on things which change during compilation.
|
||||
std::vector<std::function<void()>> fixup_hooks_in;
|
||||
// Intentionally not a small vector, this one is rare, and std::function can be large.
|
||||
Vector<std::function<void()>> fixup_hooks_in;
|
||||
|
||||
// On function entry, make sure to copy a constant array into thread addr space to work around
|
||||
// the case where we are passing a constant array by value to a function on backends which do not
|
||||
// consider arrays value types.
|
||||
std::vector<uint32_t> constant_arrays_needed_on_stack;
|
||||
SmallVector<uint32_t> constant_arrays_needed_on_stack;
|
||||
|
||||
bool active = false;
|
||||
bool flush_undeclared = true;
|
||||
@ -901,7 +1428,7 @@ struct SPIRAccessChain : IVariant
|
||||
|
||||
// By reading this expression, we implicitly read these expressions as well.
|
||||
// Used by access chain Store and Load since we read multiple expressions in this case.
|
||||
std::vector<uint32_t> implied_read_expressions;
|
||||
SmallVector<uint32_t> implied_read_expressions;
|
||||
|
||||
SPIRV_CROSS_DECLARE_CLONE(SPIRAccessChain)
|
||||
};
|
||||
@ -928,7 +1455,7 @@ struct SPIRVariable : IVariant
|
||||
uint32_t initializer = 0;
|
||||
uint32_t basevariable = 0;
|
||||
|
||||
std::vector<uint32_t> dereference_chain;
|
||||
SmallVector<uint32_t> dereference_chain;
|
||||
bool compat_builtin = false;
|
||||
|
||||
// If a variable is shadowed, we only statically assign to it
|
||||
@ -939,7 +1466,7 @@ struct SPIRVariable : IVariant
|
||||
uint32_t static_expression = 0;
|
||||
|
||||
// Temporaries which can remain forwarded as long as this variable is not modified.
|
||||
std::vector<uint32_t> dependees;
|
||||
SmallVector<uint32_t> dependees;
|
||||
bool forwardable = true;
|
||||
|
||||
bool deferred_declaration = false;
|
||||
@ -1178,7 +1705,7 @@ struct SPIRConstant : IVariant
|
||||
: constant_type(constant_type_)
|
||||
, specialization(specialized)
|
||||
{
|
||||
subconstants.insert(end(subconstants), elements, elements + num_elements);
|
||||
subconstants.insert(std::end(subconstants), elements, elements + num_elements);
|
||||
specialization = specialized;
|
||||
}
|
||||
|
||||
@ -1247,7 +1774,7 @@ struct SPIRConstant : IVariant
|
||||
bool is_used_as_lut = false;
|
||||
|
||||
// For composites which are constant arrays, etc.
|
||||
std::vector<uint32_t> subconstants;
|
||||
SmallVector<uint32_t> subconstants;
|
||||
|
||||
// Non-Vulkan GLSL, HLSL and sometimes MSL emits defines for each specialization constant,
|
||||
// and uses them to initialize the constant. This allows the user
|
||||
@ -1258,11 +1785,25 @@ struct SPIRConstant : IVariant
|
||||
SPIRV_CROSS_DECLARE_CLONE(SPIRConstant)
|
||||
};
|
||||
|
||||
// Variants have a very specific allocation scheme.
|
||||
struct ObjectPoolGroup
|
||||
{
|
||||
std::unique_ptr<ObjectPoolBase> pools[TypeCount];
|
||||
};
|
||||
|
||||
class Variant
|
||||
{
|
||||
public:
|
||||
// MSVC 2013 workaround, we shouldn't need these constructors.
|
||||
Variant() = default;
|
||||
explicit Variant(ObjectPoolGroup *group_)
|
||||
: group(group_)
|
||||
{
|
||||
}
|
||||
|
||||
~Variant()
|
||||
{
|
||||
if (holder)
|
||||
group->pools[type]->free_opaque(holder);
|
||||
}
|
||||
|
||||
// Marking custom move constructor as noexcept is important.
|
||||
Variant(Variant &&other) SPIRV_CROSS_NOEXCEPT
|
||||
@ -1270,19 +1811,23 @@ public:
|
||||
*this = std::move(other);
|
||||
}
|
||||
|
||||
Variant(const Variant &variant)
|
||||
{
|
||||
*this = variant;
|
||||
}
|
||||
// We cannot copy from other variant without our own pool group.
|
||||
// Have to explicitly copy.
|
||||
Variant(const Variant &variant) = delete;
|
||||
|
||||
// Marking custom move constructor as noexcept is important.
|
||||
Variant &operator=(Variant &&other) SPIRV_CROSS_NOEXCEPT
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
holder = std::move(other.holder);
|
||||
if (holder)
|
||||
group->pools[type]->free_opaque(holder);
|
||||
holder = other.holder;
|
||||
group = other.group;
|
||||
type = other.type;
|
||||
allow_type_rewrite = other.allow_type_rewrite;
|
||||
|
||||
other.holder = nullptr;
|
||||
other.type = TypeNone;
|
||||
}
|
||||
return *this;
|
||||
@ -1298,24 +1843,37 @@ public:
|
||||
#endif
|
||||
if (this != &other)
|
||||
{
|
||||
holder.reset();
|
||||
if (holder)
|
||||
group->pools[type]->free_opaque(holder);
|
||||
|
||||
if (other.holder)
|
||||
holder = other.holder->clone();
|
||||
holder = other.holder->clone(group->pools[other.type].get());
|
||||
|
||||
type = other.type;
|
||||
allow_type_rewrite = other.allow_type_rewrite;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void set(std::unique_ptr<IVariant> val, Types new_type)
|
||||
void set(IVariant *val, Types new_type)
|
||||
{
|
||||
holder = std::move(val);
|
||||
if (holder)
|
||||
group->pools[type]->free_opaque(holder);
|
||||
holder = val;
|
||||
if (!allow_type_rewrite && type != TypeNone && type != new_type)
|
||||
SPIRV_CROSS_THROW("Overwriting a variant with new type.");
|
||||
type = new_type;
|
||||
allow_type_rewrite = false;
|
||||
}
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
T *allocate_and_set(Types new_type, Ts &&... ts)
|
||||
{
|
||||
T *val = static_cast<ObjectPool<T> &>(*group->pools[new_type]).allocate(std::forward<Ts>(ts)...);
|
||||
set(val, new_type);
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T &get()
|
||||
{
|
||||
@ -1323,7 +1881,7 @@ public:
|
||||
SPIRV_CROSS_THROW("nullptr");
|
||||
if (static_cast<Types>(T::type) != type)
|
||||
SPIRV_CROSS_THROW("Bad cast");
|
||||
return *static_cast<T *>(holder.get());
|
||||
return *static_cast<T *>(holder);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -1333,7 +1891,7 @@ public:
|
||||
SPIRV_CROSS_THROW("nullptr");
|
||||
if (static_cast<Types>(T::type) != type)
|
||||
SPIRV_CROSS_THROW("Bad cast");
|
||||
return *static_cast<const T *>(holder.get());
|
||||
return *static_cast<const T *>(holder);
|
||||
}
|
||||
|
||||
Types get_type() const
|
||||
@ -1353,7 +1911,9 @@ public:
|
||||
|
||||
void reset()
|
||||
{
|
||||
holder.reset();
|
||||
if (holder)
|
||||
group->pools[type]->free_opaque(holder);
|
||||
holder = nullptr;
|
||||
type = TypeNone;
|
||||
}
|
||||
|
||||
@ -1363,7 +1923,8 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<IVariant> holder;
|
||||
ObjectPoolGroup *group = nullptr;
|
||||
IVariant *holder = nullptr;
|
||||
Types type = TypeNone;
|
||||
bool allow_type_rewrite = false;
|
||||
};
|
||||
@ -1383,9 +1944,7 @@ const T &variant_get(const Variant &var)
|
||||
template <typename T, typename... P>
|
||||
T &variant_set(Variant &var, P &&... args)
|
||||
{
|
||||
auto uptr = std::unique_ptr<T>(new T(std::forward<P>(args)...));
|
||||
auto ptr = uptr.get();
|
||||
var.set(std::move(uptr), static_cast<Types>(T::type));
|
||||
auto *ptr = var.allocate_and_set<T>(static_cast<Types>(T::type), std::forward<P>(args)...);
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
@ -1430,7 +1989,9 @@ struct Meta
|
||||
};
|
||||
|
||||
Decoration decoration;
|
||||
std::vector<Decoration> members;
|
||||
|
||||
// Intentionally not a SmallVector. Decoration is large and somewhat rare.
|
||||
Vector<Decoration> members;
|
||||
|
||||
std::unordered_map<uint32_t, uint32_t> decoration_word_offset;
|
||||
|
||||
@ -1529,6 +2090,6 @@ static inline bool opcode_is_sign_invariant(spv::Op opcode)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // namespace spirv_cross
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -334,7 +334,7 @@ string CompilerCPP::compile()
|
||||
reset();
|
||||
|
||||
// Move constructor for this type is broken on GCC 4.9 ...
|
||||
buffer = unique_ptr<ostringstream>(new ostringstream());
|
||||
buffer.reset();
|
||||
|
||||
emit_header();
|
||||
emit_resources();
|
||||
@ -355,7 +355,7 @@ string CompilerCPP::compile()
|
||||
// Entry point in CPP is always main() for the time being.
|
||||
get_entry_point().name = "main";
|
||||
|
||||
return buffer->str();
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
void CompilerCPP::emit_c_linkage()
|
||||
|
@ -19,15 +19,14 @@
|
||||
|
||||
#include "spirv_glsl.hpp"
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace SPIRV_CROSS_NAMESPACE
|
||||
{
|
||||
class CompilerCPP : public CompilerGLSL
|
||||
{
|
||||
public:
|
||||
explicit CompilerCPP(std::vector<uint32_t> spirv_)
|
||||
: CompilerGLSL(move(spirv_))
|
||||
explicit CompilerCPP(SmallVector<uint32_t> spirv_)
|
||||
: CompilerGLSL(std::move(spirv_))
|
||||
{
|
||||
}
|
||||
|
||||
@ -75,13 +74,13 @@ private:
|
||||
|
||||
std::string argument_decl(const SPIRFunction::Parameter &arg);
|
||||
|
||||
std::vector<std::string> resource_registrations;
|
||||
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 SPIRV_CROSS_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -26,7 +26,7 @@ using namespace std;
|
||||
using namespace spv;
|
||||
using namespace SPIRV_CROSS_NAMESPACE;
|
||||
|
||||
Compiler::Compiler(vector<uint32_t> ir_)
|
||||
Compiler::Compiler(SmallVector<uint32_t> ir_)
|
||||
{
|
||||
Parser parser(move(ir_));
|
||||
parser.parse();
|
||||
@ -1897,9 +1897,9 @@ bool Compiler::BufferAccessHandler::handle(Op opcode, const uint32_t *args, uint
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<BufferRange> Compiler::get_active_buffer_ranges(uint32_t id) const
|
||||
SmallVector<BufferRange> Compiler::get_active_buffer_ranges(uint32_t id) const
|
||||
{
|
||||
std::vector<BufferRange> ranges;
|
||||
SmallVector<BufferRange> ranges;
|
||||
BufferAccessHandler handler(*this, ranges, id);
|
||||
traverse_all_reachable_opcodes(get<SPIRFunction>(ir.default_entry_point), handler);
|
||||
return ranges;
|
||||
@ -2126,9 +2126,9 @@ void Compiler::inherit_expression_dependencies(uint32_t dst, uint32_t source_exp
|
||||
e_deps.erase(unique(begin(e_deps), end(e_deps)), end(e_deps));
|
||||
}
|
||||
|
||||
vector<EntryPoint> Compiler::get_entry_points_and_stages() const
|
||||
SmallVector<EntryPoint> Compiler::get_entry_points_and_stages() const
|
||||
{
|
||||
vector<EntryPoint> entries;
|
||||
SmallVector<EntryPoint> entries;
|
||||
for (auto &entry : ir.entry_points)
|
||||
entries.push_back({ entry.second.orig_name, entry.second.model });
|
||||
return entries;
|
||||
@ -2715,9 +2715,9 @@ void Compiler::build_combined_image_samplers()
|
||||
traverse_all_reachable_opcodes(get<SPIRFunction>(ir.default_entry_point), handler);
|
||||
}
|
||||
|
||||
vector<SpecializationConstant> Compiler::get_specialization_constants() const
|
||||
SmallVector<SpecializationConstant> Compiler::get_specialization_constants() const
|
||||
{
|
||||
vector<SpecializationConstant> spec_consts;
|
||||
SmallVector<SpecializationConstant> spec_consts;
|
||||
ir.for_each_typed_id<SPIRConstant>([&](uint32_t, const SPIRConstant &c) {
|
||||
if (c.specialization && has_decoration(c.self, DecorationSpecId))
|
||||
spec_consts.push_back({ c.self, get_decoration(c.self, DecorationSpecId) });
|
||||
@ -3966,7 +3966,7 @@ void Compiler::make_constant_null(uint32_t id, uint32_t type)
|
||||
if (!constant_type.array_size_literal.back())
|
||||
SPIRV_CROSS_THROW("Array size of OpConstantNull must be a literal.");
|
||||
|
||||
vector<uint32_t> elements(constant_type.array.back());
|
||||
SmallVector<uint32_t> elements(constant_type.array.back());
|
||||
for (uint32_t i = 0; i < constant_type.array.back(); i++)
|
||||
elements[i] = parent_id;
|
||||
set<SPIRConstant>(id, type, elements.data(), uint32_t(elements.size()), false);
|
||||
@ -3974,7 +3974,7 @@ void Compiler::make_constant_null(uint32_t id, uint32_t type)
|
||||
else if (!constant_type.member_types.empty())
|
||||
{
|
||||
uint32_t member_ids = ir.increase_bound_by(uint32_t(constant_type.member_types.size()));
|
||||
vector<uint32_t> elements(constant_type.member_types.size());
|
||||
SmallVector<uint32_t> elements(constant_type.member_types.size());
|
||||
for (uint32_t i = 0; i < constant_type.member_types.size(); i++)
|
||||
{
|
||||
make_constant_null(member_ids + i, constant_type.member_types[i]);
|
||||
@ -3989,12 +3989,12 @@ void Compiler::make_constant_null(uint32_t id, uint32_t type)
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<spv::Capability> &Compiler::get_declared_capabilities() const
|
||||
const SmallVector<spv::Capability> &Compiler::get_declared_capabilities() const
|
||||
{
|
||||
return ir.declared_capabilities;
|
||||
}
|
||||
|
||||
const std::vector<std::string> &Compiler::get_declared_extensions() const
|
||||
const SmallVector<std::string> &Compiler::get_declared_extensions() const
|
||||
{
|
||||
return ir.declared_extensions;
|
||||
}
|
||||
|
@ -54,24 +54,24 @@ struct Resource
|
||||
|
||||
struct ShaderResources
|
||||
{
|
||||
std::vector<Resource> uniform_buffers;
|
||||
std::vector<Resource> storage_buffers;
|
||||
std::vector<Resource> stage_inputs;
|
||||
std::vector<Resource> stage_outputs;
|
||||
std::vector<Resource> subpass_inputs;
|
||||
std::vector<Resource> storage_images;
|
||||
std::vector<Resource> sampled_images;
|
||||
std::vector<Resource> atomic_counters;
|
||||
std::vector<Resource> acceleration_structures;
|
||||
SmallVector<Resource> uniform_buffers;
|
||||
SmallVector<Resource> storage_buffers;
|
||||
SmallVector<Resource> stage_inputs;
|
||||
SmallVector<Resource> stage_outputs;
|
||||
SmallVector<Resource> subpass_inputs;
|
||||
SmallVector<Resource> storage_images;
|
||||
SmallVector<Resource> sampled_images;
|
||||
SmallVector<Resource> atomic_counters;
|
||||
SmallVector<Resource> acceleration_structures;
|
||||
|
||||
// There can only be one push constant block,
|
||||
// but keep the vector in case this restriction is lifted in the future.
|
||||
std::vector<Resource> push_constant_buffers;
|
||||
SmallVector<Resource> push_constant_buffers;
|
||||
|
||||
// For Vulkan GLSL and HLSL source,
|
||||
// these correspond to separate texture2D and samplers respectively.
|
||||
std::vector<Resource> separate_images;
|
||||
std::vector<Resource> separate_samplers;
|
||||
SmallVector<Resource> separate_images;
|
||||
SmallVector<Resource> separate_samplers;
|
||||
};
|
||||
|
||||
struct CombinedImageSampler
|
||||
@ -133,7 +133,7 @@ public:
|
||||
// The constructor takes a buffer of SPIR-V words and parses it.
|
||||
// It will create its own parser, parse the SPIR-V and move the parsed IR
|
||||
// as if you had called the constructors taking ParsedIR directly.
|
||||
explicit Compiler(std::vector<uint32_t> ir);
|
||||
explicit Compiler(SmallVector<uint32_t> ir);
|
||||
Compiler(const uint32_t *ir, size_t word_count);
|
||||
|
||||
// This is more modular. We can also consume a ParsedIR structure directly, either as a move, or copy.
|
||||
@ -235,7 +235,7 @@ public:
|
||||
// SPIR-V shader. The granularity of this analysis is per-member of a struct.
|
||||
// This can be used for Buffer (UBO), BufferBlock/StorageBuffer (SSBO) and PushConstant blocks.
|
||||
// ID is the Resource::id obtained from get_shader_resources().
|
||||
std::vector<BufferRange> get_active_buffer_ranges(uint32_t id) const;
|
||||
SmallVector<BufferRange> get_active_buffer_ranges(uint32_t id) const;
|
||||
|
||||
// Returns the effective size of a buffer block.
|
||||
size_t get_declared_struct_size(const SPIRType &struct_type) const;
|
||||
@ -308,7 +308,7 @@ public:
|
||||
// New variants of entry point query and reflection.
|
||||
// Names for entry points in the SPIR-V module may alias if they belong to different execution models.
|
||||
// To disambiguate, we must pass along with the entry point names the execution model.
|
||||
std::vector<EntryPoint> get_entry_points_and_stages() const;
|
||||
SmallVector<EntryPoint> get_entry_points_and_stages() const;
|
||||
void set_entry_point(const std::string &entry, spv::ExecutionModel execution_model);
|
||||
|
||||
// Renames an entry point from old_name to new_name.
|
||||
@ -392,7 +392,7 @@ public:
|
||||
void build_combined_image_samplers();
|
||||
|
||||
// Gets a remapping for the combined image samplers.
|
||||
const std::vector<CombinedImageSampler> &get_combined_image_samplers() const
|
||||
const SmallVector<CombinedImageSampler> &get_combined_image_samplers() const
|
||||
{
|
||||
return combined_image_samplers;
|
||||
}
|
||||
@ -417,7 +417,7 @@ public:
|
||||
// For composite types, the subconstants can be iterated over and modified.
|
||||
// constant_type is the SPIRType for the specialization constant,
|
||||
// which can be queried to determine which fields in the unions should be poked at.
|
||||
std::vector<SpecializationConstant> get_specialization_constants() const;
|
||||
SmallVector<SpecializationConstant> get_specialization_constants() const;
|
||||
SPIRConstant &get_constant(uint32_t id);
|
||||
const SPIRConstant &get_constant(uint32_t id) const;
|
||||
|
||||
@ -468,10 +468,10 @@ public:
|
||||
bool buffer_get_hlsl_counter_buffer(uint32_t id, uint32_t &counter_id) const;
|
||||
|
||||
// Gets the list of all SPIR-V Capabilities which were declared in the SPIR-V module.
|
||||
const std::vector<spv::Capability> &get_declared_capabilities() const;
|
||||
const SmallVector<spv::Capability> &get_declared_capabilities() const;
|
||||
|
||||
// Gets the list of all SPIR-V extensions which were declared in the SPIR-V module.
|
||||
const std::vector<std::string> &get_declared_extensions() const;
|
||||
const SmallVector<std::string> &get_declared_extensions() const;
|
||||
|
||||
// When declaring buffer blocks in GLSL, the name declared in the GLSL source
|
||||
// might not be the same as the name declared in the SPIR-V module due to naming conflicts.
|
||||
@ -511,8 +511,8 @@ protected:
|
||||
ParsedIR ir;
|
||||
// Marks variables which have global scope and variables which can alias with other variables
|
||||
// (SSBO, image load store, etc)
|
||||
std::vector<uint32_t> global_variables;
|
||||
std::vector<uint32_t> aliased_variables;
|
||||
SmallVector<uint32_t> global_variables;
|
||||
SmallVector<uint32_t> aliased_variables;
|
||||
|
||||
SPIRFunction *current_function = nullptr;
|
||||
SPIRBlock *current_block = nullptr;
|
||||
@ -686,7 +686,7 @@ protected:
|
||||
// variable is part of that entry points interface.
|
||||
bool interface_variable_exists_in_entry_point(uint32_t id) const;
|
||||
|
||||
std::vector<CombinedImageSampler> combined_image_samplers;
|
||||
SmallVector<CombinedImageSampler> combined_image_samplers;
|
||||
|
||||
void remap_variable_type_name(const SPIRType &type, const std::string &var_name, std::string &type_name) const
|
||||
{
|
||||
@ -729,7 +729,7 @@ protected:
|
||||
|
||||
struct BufferAccessHandler : OpcodeHandler
|
||||
{
|
||||
BufferAccessHandler(const Compiler &compiler_, std::vector<BufferRange> &ranges_, uint32_t id_)
|
||||
BufferAccessHandler(const Compiler &compiler_, SmallVector<BufferRange> &ranges_, uint32_t id_)
|
||||
: compiler(compiler_)
|
||||
, ranges(ranges_)
|
||||
, id(id_)
|
||||
@ -739,7 +739,7 @@ protected:
|
||||
bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override;
|
||||
|
||||
const Compiler &compiler;
|
||||
std::vector<BufferRange> &ranges;
|
||||
SmallVector<BufferRange> &ranges;
|
||||
uint32_t id;
|
||||
|
||||
std::unordered_set<uint32_t> seen;
|
||||
@ -810,7 +810,7 @@ protected:
|
||||
bool traverse_all_reachable_opcodes(const SPIRBlock &block, OpcodeHandler &handler) const;
|
||||
bool traverse_all_reachable_opcodes(const SPIRFunction &block, OpcodeHandler &handler) const;
|
||||
// This must be an ordered data structure so we always pick the same type aliases.
|
||||
std::vector<uint32_t> global_struct_cache;
|
||||
SmallVector<uint32_t> global_struct_cache;
|
||||
|
||||
ShaderResources get_shader_resources(const std::unordered_set<uint32_t> *active_variables) const;
|
||||
|
||||
@ -967,6 +967,6 @@ private:
|
||||
bool type_is_block_like(const SPIRType &type) const;
|
||||
bool type_is_opaque_value(const SPIRType &type) const;
|
||||
};
|
||||
} // namespace spirv_cross
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -34,9 +34,9 @@
|
||||
#include "spirv_reflect.hpp"
|
||||
#endif
|
||||
#include "spirv_parser.hpp"
|
||||
#include <string.h>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <string.h>
|
||||
|
||||
// clang-format off
|
||||
|
||||
@ -88,7 +88,7 @@ struct StringAllocation : ScratchMemoryAllocation
|
||||
template <typename T>
|
||||
struct TemporaryBuffer : ScratchMemoryAllocation
|
||||
{
|
||||
std::vector<T> buffer;
|
||||
SmallVector<T> buffer;
|
||||
};
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
@ -100,7 +100,7 @@ static inline std::unique_ptr<T> spvc_allocate(Ts &&... ts)
|
||||
struct spvc_context_s
|
||||
{
|
||||
string last_error;
|
||||
vector<unique_ptr<ScratchMemoryAllocation>> allocations;
|
||||
SmallVector<unique_ptr<ScratchMemoryAllocation>> allocations;
|
||||
const char *allocate_name(const std::string &name);
|
||||
|
||||
spvc_error_callback callback = nullptr;
|
||||
@ -173,20 +173,20 @@ struct spvc_constant_s : SPIRConstant
|
||||
struct spvc_resources_s : ScratchMemoryAllocation
|
||||
{
|
||||
spvc_context context = nullptr;
|
||||
std::vector<spvc_reflected_resource> uniform_buffers;
|
||||
std::vector<spvc_reflected_resource> storage_buffers;
|
||||
std::vector<spvc_reflected_resource> stage_inputs;
|
||||
std::vector<spvc_reflected_resource> stage_outputs;
|
||||
std::vector<spvc_reflected_resource> subpass_inputs;
|
||||
std::vector<spvc_reflected_resource> storage_images;
|
||||
std::vector<spvc_reflected_resource> sampled_images;
|
||||
std::vector<spvc_reflected_resource> atomic_counters;
|
||||
std::vector<spvc_reflected_resource> push_constant_buffers;
|
||||
std::vector<spvc_reflected_resource> separate_images;
|
||||
std::vector<spvc_reflected_resource> separate_samplers;
|
||||
std::vector<spvc_reflected_resource> acceleration_structures;
|
||||
SmallVector<spvc_reflected_resource> uniform_buffers;
|
||||
SmallVector<spvc_reflected_resource> storage_buffers;
|
||||
SmallVector<spvc_reflected_resource> stage_inputs;
|
||||
SmallVector<spvc_reflected_resource> stage_outputs;
|
||||
SmallVector<spvc_reflected_resource> subpass_inputs;
|
||||
SmallVector<spvc_reflected_resource> storage_images;
|
||||
SmallVector<spvc_reflected_resource> sampled_images;
|
||||
SmallVector<spvc_reflected_resource> atomic_counters;
|
||||
SmallVector<spvc_reflected_resource> push_constant_buffers;
|
||||
SmallVector<spvc_reflected_resource> separate_images;
|
||||
SmallVector<spvc_reflected_resource> separate_samplers;
|
||||
SmallVector<spvc_reflected_resource> acceleration_structures;
|
||||
|
||||
bool copy_resources(std::vector<spvc_reflected_resource> &outputs, const std::vector<Resource> &inputs);
|
||||
bool copy_resources(SmallVector<spvc_reflected_resource> &outputs, const SmallVector<Resource> &inputs);
|
||||
bool copy_resources(const ShaderResources &resources);
|
||||
};
|
||||
|
||||
@ -634,7 +634,7 @@ spvc_result spvc_compiler_hlsl_set_root_constants_layout(spvc_compiler compiler,
|
||||
}
|
||||
|
||||
auto &hlsl = *static_cast<CompilerHLSL *>(compiler->compiler.get());
|
||||
std::vector<RootConstants> roots;
|
||||
SmallVector<RootConstants> roots;
|
||||
roots.reserve(count);
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
@ -980,8 +980,8 @@ spvc_result spvc_compiler_compile(spvc_compiler compiler, const char **source)
|
||||
SPVC_END_SAFE_SCOPE(compiler->context, SPVC_ERROR_UNSUPPORTED_SPIRV)
|
||||
}
|
||||
|
||||
bool spvc_resources_s::copy_resources(std::vector<spvc_reflected_resource> &outputs,
|
||||
const std::vector<Resource> &inputs)
|
||||
bool spvc_resources_s::copy_resources(SmallVector<spvc_reflected_resource> &outputs,
|
||||
const SmallVector<Resource> &inputs)
|
||||
{
|
||||
for (auto &i : inputs)
|
||||
{
|
||||
@ -1117,7 +1117,7 @@ spvc_result spvc_resources_get_resource_list_for_type(spvc_resources resources,
|
||||
const spvc_reflected_resource **resource_list,
|
||||
size_t *resource_size)
|
||||
{
|
||||
const std::vector<spvc_reflected_resource> *list = nullptr;
|
||||
const SmallVector<spvc_reflected_resource> *list = nullptr;
|
||||
switch (type)
|
||||
{
|
||||
case SPVC_RESOURCE_TYPE_UNIFORM_BUFFER:
|
||||
@ -1275,7 +1275,7 @@ spvc_result spvc_compiler_get_entry_points(spvc_compiler compiler, const spvc_en
|
||||
SPVC_BEGIN_SAFE_SCOPE
|
||||
{
|
||||
auto entries = compiler->compiler->get_entry_points_and_stages();
|
||||
std::vector<spvc_entry_point> translated;
|
||||
SmallVector<spvc_entry_point> translated;
|
||||
translated.reserve(entries.size());
|
||||
|
||||
for (auto &entry : entries)
|
||||
@ -1406,7 +1406,7 @@ unsigned spvc_type_get_bit_width(spvc_type type)
|
||||
return type->width;
|
||||
}
|
||||
|
||||
unsigned spvc_type_get_vector_size(spvc_type type)
|
||||
unsigned spvc_type_get_SmallVector_size(spvc_type type)
|
||||
{
|
||||
return type->vecsize;
|
||||
}
|
||||
@ -1566,7 +1566,7 @@ spvc_result spvc_compiler_get_combined_image_samplers(spvc_compiler compiler,
|
||||
SPVC_BEGIN_SAFE_SCOPE
|
||||
{
|
||||
auto combined = compiler->compiler->get_combined_image_samplers();
|
||||
std::vector<spvc_combined_image_sampler> translated;
|
||||
SmallVector<spvc_combined_image_sampler> translated;
|
||||
translated.reserve(combined.size());
|
||||
for (auto &c : combined)
|
||||
{
|
||||
@ -1591,7 +1591,7 @@ spvc_result spvc_compiler_get_specialization_constants(spvc_compiler compiler,
|
||||
SPVC_BEGIN_SAFE_SCOPE
|
||||
{
|
||||
auto spec_constants = compiler->compiler->get_specialization_constants();
|
||||
std::vector<spvc_specialization_constant> translated;
|
||||
SmallVector<spvc_specialization_constant> translated;
|
||||
translated.reserve(spec_constants.size());
|
||||
for (auto &c : spec_constants)
|
||||
{
|
||||
@ -1743,7 +1743,7 @@ spvc_result spvc_compiler_get_declared_extensions(spvc_compiler compiler, const
|
||||
SPVC_BEGIN_SAFE_SCOPE
|
||||
{
|
||||
auto &exts = compiler->compiler->get_declared_extensions();
|
||||
std::vector<const char *> duped;
|
||||
SmallVector<const char *> duped;
|
||||
duped.reserve(exts.size());
|
||||
for (auto &ext : exts)
|
||||
duped.push_back(compiler->context->allocate_name(ext));
|
||||
|
@ -23,9 +23,70 @@ using namespace spv;
|
||||
|
||||
namespace SPIRV_CROSS_NAMESPACE
|
||||
{
|
||||
ParsedIR::ParsedIR()
|
||||
{
|
||||
// If we move ParsedIR, we need to make sure the pointer stays fixed since the child Variant objects consume a pointer to this group,
|
||||
// so need an extra pointer here.
|
||||
pool_group.reset(new ObjectPoolGroup);
|
||||
|
||||
pool_group->pools[TypeType].reset(new ObjectPool<SPIRType>);
|
||||
pool_group->pools[TypeVariable].reset(new ObjectPool<SPIRVariable>);
|
||||
pool_group->pools[TypeConstant].reset(new ObjectPool<SPIRConstant>);
|
||||
pool_group->pools[TypeFunction].reset(new ObjectPool<SPIRFunction>);
|
||||
pool_group->pools[TypeFunctionPrototype].reset(new ObjectPool<SPIRFunctionPrototype>);
|
||||
pool_group->pools[TypeBlock].reset(new ObjectPool<SPIRBlock>);
|
||||
pool_group->pools[TypeExtension].reset(new ObjectPool<SPIRExtension>);
|
||||
pool_group->pools[TypeExpression].reset(new ObjectPool<SPIRExpression>);
|
||||
pool_group->pools[TypeConstantOp].reset(new ObjectPool<SPIRConstantOp>);
|
||||
pool_group->pools[TypeCombinedImageSampler].reset(new ObjectPool<SPIRCombinedImageSampler>);
|
||||
pool_group->pools[TypeAccessChain].reset(new ObjectPool<SPIRAccessChain>);
|
||||
pool_group->pools[TypeUndef].reset(new ObjectPool<SPIRUndef>);
|
||||
}
|
||||
|
||||
ParsedIR::ParsedIR(const ParsedIR &other)
|
||||
: ParsedIR()
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
ParsedIR &ParsedIR::operator=(const ParsedIR &other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
spirv = other.spirv;
|
||||
meta = other.meta;
|
||||
for (int i = 0; i < TypeCount; i++)
|
||||
ids_for_type[i] = other.ids_for_type[i];
|
||||
ids_for_constant_or_type = other.ids_for_constant_or_type;
|
||||
ids_for_constant_or_variable = other.ids_for_constant_or_variable;
|
||||
declared_capabilities = other.declared_capabilities;
|
||||
declared_extensions = other.declared_extensions;
|
||||
block_meta = other.block_meta;
|
||||
continue_block_to_loop_header = other.continue_block_to_loop_header;
|
||||
entry_points = other.entry_points;
|
||||
default_entry_point = other.default_entry_point;
|
||||
source = other.source;
|
||||
loop_iteration_depth = other.loop_iteration_depth;
|
||||
|
||||
// Very deliberate copying of IDs. There is no default copy constructor, nor a simple default constructor.
|
||||
// Construct object first so we have the correct allocator set-up, then we can copy object into our new pool group.
|
||||
ids.clear();
|
||||
ids.reserve(other.ids.size());
|
||||
for (size_t i = 0; i < other.ids.size(); i++)
|
||||
{
|
||||
ids.emplace_back(pool_group.get());
|
||||
ids.back() = other.ids[i];
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ParsedIR::set_id_bounds(uint32_t bounds)
|
||||
{
|
||||
ids.resize(bounds);
|
||||
ids.reserve(bounds);
|
||||
while (ids.size() < bounds)
|
||||
ids.emplace_back(pool_group.get());
|
||||
|
||||
block_meta.resize(bounds);
|
||||
}
|
||||
|
||||
@ -571,7 +632,11 @@ uint32_t ParsedIR::increase_bound_by(uint32_t incr_amount)
|
||||
{
|
||||
auto curr_bound = ids.size();
|
||||
auto new_bound = curr_bound + incr_amount;
|
||||
ids.resize(new_bound);
|
||||
|
||||
ids.reserve(ids.size() + incr_amount);
|
||||
for (uint32_t i = 0; i < incr_amount; i++)
|
||||
ids.emplace_back(pool_group.get());
|
||||
|
||||
block_meta.resize(new_bound);
|
||||
return uint32_t(curr_bound);
|
||||
}
|
||||
@ -645,4 +710,4 @@ Meta *ParsedIR::find_meta(uint32_t id)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace spirv_cross
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "spirv_common.hpp"
|
||||
#include <stdint.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace SPIRV_CROSS_NAMESPACE
|
||||
{
|
||||
@ -32,15 +31,29 @@ namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
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.
|
||||
ParsedIR(ParsedIR &&other) = default;
|
||||
ParsedIR &operator=(ParsedIR &&other) = default;
|
||||
|
||||
// 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;
|
||||
SmallVector<uint32_t> spirv;
|
||||
|
||||
// Holds various data structures which inherit from IVariant.
|
||||
std::vector<Variant> ids;
|
||||
SmallVector<Variant> ids;
|
||||
|
||||
// Various meta data for IDs, decorations, names, etc.
|
||||
std::unordered_map<uint32_t, Meta> meta;
|
||||
@ -48,19 +61,19 @@ public:
|
||||
// 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.
|
||||
std::vector<uint32_t> ids_for_type[TypeCount];
|
||||
SmallVector<uint32_t> 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.
|
||||
std::vector<uint32_t> ids_for_constant_or_type;
|
||||
std::vector<uint32_t> ids_for_constant_or_variable;
|
||||
SmallVector<uint32_t> ids_for_constant_or_type;
|
||||
SmallVector<uint32_t> ids_for_constant_or_variable;
|
||||
|
||||
// Declared capabilities and extensions in the SPIR-V module.
|
||||
// Not really used except for reflection at the moment.
|
||||
std::vector<spv::Capability> declared_capabilities;
|
||||
std::vector<std::string> declared_extensions;
|
||||
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.
|
||||
@ -73,7 +86,7 @@ public:
|
||||
BLOCK_META_MULTISELECT_MERGE_BIT = 1 << 4
|
||||
};
|
||||
using BlockMetaFlags = uint8_t;
|
||||
std::vector<BlockMetaFlags> block_meta;
|
||||
SmallVector<BlockMetaFlags> block_meta;
|
||||
std::unordered_map<uint32_t, uint32_t> continue_block_to_loop_header;
|
||||
|
||||
// Normally, we'd stick SPIREntryPoint in ids array, but it conflicts with SPIRFunction.
|
||||
@ -181,6 +194,6 @@ private:
|
||||
std::string empty_string;
|
||||
Bitset cleared_bitset;
|
||||
};
|
||||
} // namespace spirv_cross
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -22,8 +22,8 @@ using namespace SPIRV_CROSS_NAMESPACE;
|
||||
|
||||
namespace spirv_cross_util
|
||||
{
|
||||
void rename_interface_variable(Compiler &compiler, const std::vector<Resource> &resources,
|
||||
uint32_t location, const std::string &name)
|
||||
void rename_interface_variable(Compiler &compiler, const SmallVector<Resource> &resources, uint32_t location,
|
||||
const std::string &name)
|
||||
{
|
||||
for (auto &v : resources)
|
||||
{
|
||||
|
@ -21,7 +21,8 @@
|
||||
|
||||
namespace spirv_cross_util
|
||||
{
|
||||
void rename_interface_variable(SPIRV_CROSS_NAMESPACE::Compiler &compiler, const std::vector<SPIRV_CROSS_NAMESPACE::Resource> &resources,
|
||||
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
|
||||
|
@ -454,8 +454,7 @@ string CompilerGLSL::compile()
|
||||
|
||||
reset();
|
||||
|
||||
// Move constructor for this type is broken on GCC 4.9 ...
|
||||
buffer = unique_ptr<ostringstream>(new ostringstream());
|
||||
buffer.reset();
|
||||
|
||||
emit_header();
|
||||
emit_resources();
|
||||
@ -468,15 +467,15 @@ string CompilerGLSL::compile()
|
||||
// Entry point in GLSL is always main().
|
||||
get_entry_point().name = "main";
|
||||
|
||||
return buffer->str();
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
std::string CompilerGLSL::get_partial_source()
|
||||
{
|
||||
return buffer ? buffer->str() : "No compiled source available yet.";
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
void CompilerGLSL::build_workgroup_size(vector<string> &arguments, const SpecializationConstant &wg_x,
|
||||
void CompilerGLSL::build_workgroup_size(SmallVector<string> &arguments, const SpecializationConstant &wg_x,
|
||||
const SpecializationConstant &wg_y, const SpecializationConstant &wg_z)
|
||||
{
|
||||
auto &execution = get_entry_point();
|
||||
@ -573,8 +572,8 @@ void CompilerGLSL::emit_header()
|
||||
for (auto &header : header_lines)
|
||||
statement(header);
|
||||
|
||||
vector<string> inputs;
|
||||
vector<string> outputs;
|
||||
SmallVector<string> inputs;
|
||||
SmallVector<string> outputs;
|
||||
|
||||
switch (execution.model)
|
||||
{
|
||||
@ -798,7 +797,7 @@ string CompilerGLSL::layout_for_member(const SPIRType &type, uint32_t index)
|
||||
return "";
|
||||
auto &dec = memb[index];
|
||||
|
||||
vector<string> attr;
|
||||
SmallVector<string> attr;
|
||||
|
||||
// We can only apply layouts on members in block interfaces.
|
||||
// This is a bit problematic because in SPIR-V decorations are applied on the struct types directly.
|
||||
@ -1294,7 +1293,7 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var)
|
||||
if (is_legacy())
|
||||
return "";
|
||||
|
||||
vector<string> attr;
|
||||
SmallVector<string> attr;
|
||||
|
||||
auto &dec = ir.meta[var.self].decoration;
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
@ -2325,7 +2324,7 @@ void CompilerGLSL::emit_resources()
|
||||
|
||||
if ((wg_x.id != 0) || (wg_y.id != 0) || (wg_z.id != 0))
|
||||
{
|
||||
vector<string> inputs;
|
||||
SmallVector<string> inputs;
|
||||
build_workgroup_size(inputs, wg_x, wg_y, wg_z);
|
||||
statement("layout(", merge(inputs), ") in;");
|
||||
statement("");
|
||||
@ -3825,7 +3824,8 @@ void CompilerGLSL::emit_unary_func_op_cast(uint32_t result_type, uint32_t result
|
||||
auto &out_type = get<SPIRType>(result_type);
|
||||
auto expected_type = out_type;
|
||||
expected_type.basetype = input_type;
|
||||
string cast_op = expression_type(op0).basetype != input_type ? bitcast_glsl(expected_type, op0) : to_expression(op0);
|
||||
string cast_op =
|
||||
expression_type(op0).basetype != input_type ? bitcast_glsl(expected_type, op0) : to_expression(op0);
|
||||
|
||||
string expr;
|
||||
if (out_type.basetype != expected_result_type)
|
||||
@ -3845,17 +3845,18 @@ void CompilerGLSL::emit_unary_func_op_cast(uint32_t result_type, uint32_t result
|
||||
inherit_expression_dependencies(result_id, op0);
|
||||
}
|
||||
|
||||
void CompilerGLSL::emit_trinary_func_op_cast(uint32_t result_type, uint32_t result_id,
|
||||
uint32_t op0, uint32_t op1, uint32_t op2,
|
||||
const char *op,
|
||||
SPIRType::BaseType input_type)
|
||||
void CompilerGLSL::emit_trinary_func_op_cast(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1,
|
||||
uint32_t op2, const char *op, SPIRType::BaseType input_type)
|
||||
{
|
||||
auto &out_type = get<SPIRType>(result_type);
|
||||
auto expected_type = out_type;
|
||||
expected_type.basetype = input_type;
|
||||
string cast_op0 = expression_type(op0).basetype != input_type ? bitcast_glsl(expected_type, op0) : to_expression(op0);
|
||||
string cast_op1 = expression_type(op1).basetype != input_type ? bitcast_glsl(expected_type, op1) : to_expression(op1);
|
||||
string cast_op2 = expression_type(op2).basetype != input_type ? bitcast_glsl(expected_type, op2) : to_expression(op2);
|
||||
string cast_op0 =
|
||||
expression_type(op0).basetype != input_type ? bitcast_glsl(expected_type, op0) : to_expression(op0);
|
||||
string cast_op1 =
|
||||
expression_type(op1).basetype != input_type ? bitcast_glsl(expected_type, op1) : to_expression(op1);
|
||||
string cast_op2 =
|
||||
expression_type(op2).basetype != input_type ? bitcast_glsl(expected_type, op2) : to_expression(op2);
|
||||
|
||||
string expr;
|
||||
if (out_type.basetype != input_type)
|
||||
@ -4311,7 +4312,7 @@ void CompilerGLSL::emit_texture_op(const Instruction &i)
|
||||
auto op = static_cast<Op>(i.op);
|
||||
uint32_t length = i.length;
|
||||
|
||||
vector<uint32_t> inherited_expressions;
|
||||
SmallVector<uint32_t> inherited_expressions;
|
||||
|
||||
uint32_t result_type = ops[0];
|
||||
uint32_t id = ops[1];
|
||||
@ -5096,7 +5097,8 @@ void CompilerGLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
|
||||
break;
|
||||
|
||||
case GLSLstd450FindUMsb:
|
||||
emit_unary_func_op_cast(result_type, id, args[0], "findMSB", uint_type, int_type); // findMSB always returns int.
|
||||
emit_unary_func_op_cast(result_type, id, args[0], "findMSB", uint_type,
|
||||
int_type); // findMSB always returns int.
|
||||
break;
|
||||
|
||||
// Multisampled varying
|
||||
@ -7341,7 +7343,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
||||
register_impure_function_call();
|
||||
|
||||
string funexpr;
|
||||
vector<string> arglist;
|
||||
SmallVector<string> arglist;
|
||||
funexpr += to_name(func) + "(";
|
||||
|
||||
if (emit_return_value_as_argument)
|
||||
@ -7704,7 +7706,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
||||
trivial_forward = !expression_is_forwarded(vec0) && !expression_is_forwarded(vec1);
|
||||
|
||||
// Constructor style and shuffling from two different vectors.
|
||||
vector<string> args;
|
||||
SmallVector<string> args;
|
||||
for (uint32_t i = 0; i < length; i++)
|
||||
{
|
||||
if (elems[i] == 0xffffffffu)
|
||||
@ -9250,7 +9252,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
|
||||
// access to shader input content from within a function (eg. Metal). Each additional
|
||||
// function args uses the name of the global variable. Function nesting will modify the
|
||||
// functions and function calls all the way up the nesting chain.
|
||||
void CompilerGLSL::append_global_func_args(const SPIRFunction &func, uint32_t index, vector<string> &arglist)
|
||||
void CompilerGLSL::append_global_func_args(const SPIRFunction &func, uint32_t index, SmallVector<string> &arglist)
|
||||
{
|
||||
auto &args = func.arguments;
|
||||
uint32_t arg_cnt = uint32_t(args.size());
|
||||
@ -10085,7 +10087,7 @@ void CompilerGLSL::emit_function_prototype(SPIRFunction &func, const Bitset &ret
|
||||
decl += to_name(func.self);
|
||||
|
||||
decl += "(";
|
||||
vector<string> arglist;
|
||||
SmallVector<string> arglist;
|
||||
for (auto &arg : func.arguments)
|
||||
{
|
||||
// Do not pass in separate images or samplers if we're remapping
|
||||
@ -10543,7 +10545,7 @@ string CompilerGLSL::emit_continue_block(uint32_t continue_block, bool follow_tr
|
||||
// if we have to emit temporaries.
|
||||
current_continue_block = block;
|
||||
|
||||
vector<string> statements;
|
||||
SmallVector<string> statements;
|
||||
|
||||
// Capture all statements into our list.
|
||||
auto *old = redirect_statement;
|
||||
@ -10866,7 +10868,7 @@ void CompilerGLSL::flush_undeclared_variables(SPIRBlock &block)
|
||||
flush_variable_declaration(v);
|
||||
}
|
||||
|
||||
void CompilerGLSL::emit_hoisted_temporaries(vector<pair<uint32_t, uint32_t>> &temporaries)
|
||||
void CompilerGLSL::emit_hoisted_temporaries(SmallVector<pair<uint32_t, uint32_t>> &temporaries)
|
||||
{
|
||||
// If we need to force temporaries for certain IDs due to continue blocks, do it before starting loop header.
|
||||
// Need to sort these to ensure that reference output is stable.
|
||||
@ -11416,8 +11418,7 @@ void CompilerGLSL::unroll_array_from_complex_load(uint32_t target_id, uint32_t s
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerGLSL::bitcast_from_builtin_load(uint32_t source_id, std::string &expr,
|
||||
const SPIRType &expr_type)
|
||||
void CompilerGLSL::bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type)
|
||||
{
|
||||
auto *var = maybe_get_backing_variable(source_id);
|
||||
if (var)
|
||||
@ -11464,8 +11465,7 @@ void CompilerGLSL::bitcast_from_builtin_load(uint32_t source_id, std::string &ex
|
||||
expr = bitcast_expression(expr_type, expected_type, expr);
|
||||
}
|
||||
|
||||
void CompilerGLSL::bitcast_to_builtin_store(uint32_t target_id, std::string &expr,
|
||||
const SPIRType &expr_type)
|
||||
void CompilerGLSL::bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type)
|
||||
{
|
||||
// Only interested in standalone builtin variables.
|
||||
if (!has_decoration(target_id, DecorationBuiltIn))
|
||||
|
@ -17,9 +17,8 @@
|
||||
#ifndef SPIRV_CROSS_GLSL_HPP
|
||||
#define SPIRV_CROSS_GLSL_HPP
|
||||
|
||||
#include "spirv_cross.hpp"
|
||||
#include "GLSL.std.450.h"
|
||||
#include <sstream>
|
||||
#include "spirv_cross.hpp"
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
@ -134,15 +133,15 @@ public:
|
||||
} fragment;
|
||||
};
|
||||
|
||||
void remap_pixel_local_storage(std::vector<PlsRemap> inputs, std::vector<PlsRemap> outputs)
|
||||
void remap_pixel_local_storage(SmallVector<PlsRemap> inputs, SmallVector<PlsRemap> outputs)
|
||||
{
|
||||
pls_inputs = std::move(inputs);
|
||||
pls_outputs = std::move(outputs);
|
||||
remap_pls_variables();
|
||||
}
|
||||
|
||||
explicit CompilerGLSL(std::vector<uint32_t> spirv_)
|
||||
: Compiler(move(spirv_))
|
||||
explicit CompilerGLSL(SmallVector<uint32_t> spirv_)
|
||||
: Compiler(std::move(spirv_))
|
||||
{
|
||||
init();
|
||||
}
|
||||
@ -230,7 +229,7 @@ protected:
|
||||
virtual void emit_spv_amd_gcn_shader_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args,
|
||||
uint32_t count);
|
||||
virtual void emit_header();
|
||||
void build_workgroup_size(std::vector<std::string> &arguments, const SpecializationConstant &x,
|
||||
void build_workgroup_size(SmallVector<std::string> &arguments, const SpecializationConstant &x,
|
||||
const SpecializationConstant &y, const SpecializationConstant &z);
|
||||
|
||||
virtual void emit_sampled_image_op(uint32_t result_type, uint32_t result_id, uint32_t image_id, uint32_t samp_id);
|
||||
@ -260,19 +259,19 @@ protected:
|
||||
virtual void emit_uniform(const SPIRVariable &var);
|
||||
virtual std::string unpack_expression_type(std::string expr_str, const SPIRType &type, uint32_t packed_type_id);
|
||||
|
||||
std::unique_ptr<std::ostringstream> buffer;
|
||||
StringStream<> buffer;
|
||||
|
||||
template <typename T>
|
||||
inline void statement_inner(T &&t)
|
||||
{
|
||||
(*buffer) << std::forward<T>(t);
|
||||
buffer << std::forward<T>(t);
|
||||
statement_count++;
|
||||
}
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
inline void statement_inner(T &&t, Ts &&... ts)
|
||||
{
|
||||
(*buffer) << std::forward<T>(t);
|
||||
buffer << std::forward<T>(t);
|
||||
statement_count++;
|
||||
statement_inner(std::forward<Ts>(ts)...);
|
||||
}
|
||||
@ -296,9 +295,9 @@ protected:
|
||||
else
|
||||
{
|
||||
for (uint32_t i = 0; i < indent; i++)
|
||||
(*buffer) << " ";
|
||||
buffer << " ";
|
||||
statement_inner(std::forward<Ts>(ts)...);
|
||||
(*buffer) << '\n';
|
||||
buffer << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
@ -314,7 +313,7 @@ protected:
|
||||
// Used for implementing continue blocks where
|
||||
// we want to obtain a list of statements we can merge
|
||||
// on a single line separated by comma.
|
||||
std::vector<std::string> *redirect_statement = nullptr;
|
||||
SmallVector<std::string> *redirect_statement = nullptr;
|
||||
const SPIRBlock *current_continue_block = nullptr;
|
||||
|
||||
void begin_scope();
|
||||
@ -406,7 +405,7 @@ protected:
|
||||
void emit_interface_block(const SPIRVariable &type);
|
||||
void emit_flattened_io_block(const SPIRVariable &var, const char *qual);
|
||||
void emit_block_chain(SPIRBlock &block);
|
||||
void emit_hoisted_temporaries(std::vector<std::pair<uint32_t, uint32_t>> &temporaries);
|
||||
void emit_hoisted_temporaries(SmallVector<std::pair<uint32_t, uint32_t>> &temporaries);
|
||||
std::string constant_value_macro_name(uint32_t id);
|
||||
void emit_constant(const SPIRConstant &constant);
|
||||
void emit_specialization_constant_op(const SPIRConstantOp &constant);
|
||||
@ -437,8 +436,8 @@ protected:
|
||||
SPIRType::BaseType input_type, SPIRType::BaseType expected_result_type);
|
||||
void emit_binary_func_op_cast(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op,
|
||||
SPIRType::BaseType input_type, bool skip_cast_if_equal_type);
|
||||
void emit_trinary_func_op_cast(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, uint32_t op2, const char *op,
|
||||
SPIRType::BaseType input_type);
|
||||
void emit_trinary_func_op_cast(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, uint32_t op2,
|
||||
const char *op, SPIRType::BaseType input_type);
|
||||
|
||||
void emit_unary_func_op(uint32_t result_type, uint32_t result_id, uint32_t op0, const char *op);
|
||||
void emit_unrolled_unary_op(uint32_t result_type, uint32_t result_id, uint32_t operand, const char *op);
|
||||
@ -486,7 +485,7 @@ protected:
|
||||
std::string declare_temporary(uint32_t type, uint32_t id);
|
||||
void emit_uninitialized_temporary(uint32_t type, uint32_t id);
|
||||
SPIRExpression &emit_uninitialized_temporary_expression(uint32_t type, uint32_t id);
|
||||
void append_global_func_args(const SPIRFunction &func, uint32_t index, std::vector<std::string> &arglist);
|
||||
void append_global_func_args(const SPIRFunction &func, uint32_t index, SmallVector<std::string> &arglist);
|
||||
std::string to_expression(uint32_t id, bool register_expression_read = true);
|
||||
std::string to_enclosed_expression(uint32_t id, bool register_expression_read = true);
|
||||
std::string to_unpacked_expression(uint32_t id, bool register_expression_read = true);
|
||||
@ -562,8 +561,8 @@ protected:
|
||||
std::unordered_map<uint32_t, uint32_t> expression_usage_counts;
|
||||
void track_expression_read(uint32_t id);
|
||||
|
||||
std::vector<std::string> forced_extensions;
|
||||
std::vector<std::string> header_lines;
|
||||
SmallVector<std::string> forced_extensions;
|
||||
SmallVector<std::string> header_lines;
|
||||
|
||||
// Used when expressions emit extra opcodes with their own unique IDs,
|
||||
// and we need to reuse the IDs across recompilation loops.
|
||||
@ -593,8 +592,8 @@ protected:
|
||||
void register_control_dependent_expression(uint32_t expr);
|
||||
|
||||
// GL_EXT_shader_pixel_local_storage support.
|
||||
std::vector<PlsRemap> pls_inputs;
|
||||
std::vector<PlsRemap> pls_outputs;
|
||||
SmallVector<PlsRemap> pls_inputs;
|
||||
SmallVector<PlsRemap> pls_outputs;
|
||||
std::string pls_decl(const PlsRemap &variable);
|
||||
const char *to_pls_qualifiers_glsl(const SPIRVariable &variable);
|
||||
void emit_pls();
|
||||
@ -655,6 +654,6 @@ protected:
|
||||
private:
|
||||
void init();
|
||||
};
|
||||
} // namespace spirv_cross
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -1210,8 +1210,8 @@ void CompilerHLSL::emit_resources()
|
||||
require_output = false;
|
||||
unordered_set<uint32_t> active_inputs;
|
||||
unordered_set<uint32_t> active_outputs;
|
||||
vector<SPIRVariable *> input_variables;
|
||||
vector<SPIRVariable *> output_variables;
|
||||
SmallVector<SPIRVariable *> input_variables;
|
||||
SmallVector<SPIRVariable *> output_variables;
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
|
||||
auto &type = this->get<SPIRType>(var.basetype);
|
||||
bool block = ir.meta[type.self].decoration.decoration_flags.get(DecorationBlock);
|
||||
@ -2024,7 +2024,7 @@ void CompilerHLSL::emit_function_prototype(SPIRFunction &func, const Bitset &ret
|
||||
decl += to_name(func.self);
|
||||
|
||||
decl += "(";
|
||||
vector<string> arglist;
|
||||
SmallVector<string> arglist;
|
||||
|
||||
if (!type.array.empty())
|
||||
{
|
||||
@ -2092,7 +2092,7 @@ void CompilerHLSL::emit_function_prototype(SPIRFunction &func, const Bitset &ret
|
||||
|
||||
void CompilerHLSL::emit_hlsl_entry_point()
|
||||
{
|
||||
vector<string> arguments;
|
||||
SmallVector<string> arguments;
|
||||
|
||||
if (require_input)
|
||||
arguments.push_back("SPIRV_Cross_Input stage_input");
|
||||
@ -2425,7 +2425,7 @@ void CompilerHLSL::emit_texture_op(const Instruction &i)
|
||||
auto op = static_cast<Op>(i.op);
|
||||
uint32_t length = i.length;
|
||||
|
||||
vector<uint32_t> inherited_expressions;
|
||||
SmallVector<uint32_t> inherited_expressions;
|
||||
|
||||
uint32_t result_type = ops[0];
|
||||
uint32_t id = ops[1];
|
||||
@ -4565,7 +4565,7 @@ void CompilerHLSL::require_texture_query_variant(const SPIRType &type)
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerHLSL::set_root_constant_layouts(vector<RootConstants> layout)
|
||||
void CompilerHLSL::set_root_constant_layouts(SmallVector<RootConstants> layout)
|
||||
{
|
||||
root_constants_layout = move(layout);
|
||||
}
|
||||
@ -4664,7 +4664,7 @@ string CompilerHLSL::compile()
|
||||
reset();
|
||||
|
||||
// Move constructor for this type is broken on GCC 4.9 ...
|
||||
buffer = unique_ptr<ostringstream>(new ostringstream());
|
||||
buffer.reset();
|
||||
|
||||
emit_header();
|
||||
emit_resources();
|
||||
@ -4678,7 +4678,7 @@ string CompilerHLSL::compile()
|
||||
// Entry point in HLSL is always main() for the time being.
|
||||
get_entry_point().name = "main";
|
||||
|
||||
return buffer->str();
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
void CompilerHLSL::emit_block_hints(const SPIRBlock &block)
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
#include "spirv_glsl.hpp"
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace SPIRV_CROSS_NAMESPACE
|
||||
{
|
||||
@ -62,8 +61,8 @@ public:
|
||||
bool support_nonzero_base_vertex_base_instance = false;
|
||||
};
|
||||
|
||||
explicit CompilerHLSL(std::vector<uint32_t> spirv_)
|
||||
: CompilerGLSL(move(spirv_))
|
||||
explicit CompilerHLSL(SmallVector<uint32_t> spirv_)
|
||||
: CompilerGLSL(std::move(spirv_))
|
||||
{
|
||||
}
|
||||
|
||||
@ -96,7 +95,7 @@ public:
|
||||
//
|
||||
// Push constants ranges will be split up according to the
|
||||
// layout specified.
|
||||
void set_root_constant_layouts(std::vector<RootConstants> layout);
|
||||
void set_root_constant_layouts(SmallVector<RootConstants> layout);
|
||||
|
||||
// Compiles and remaps vertex attributes at specific locations to a fixed semantic.
|
||||
// The default is TEXCOORD# where # denotes location.
|
||||
@ -209,7 +208,7 @@ private:
|
||||
void emit_builtin_variables();
|
||||
bool require_output = false;
|
||||
bool require_input = false;
|
||||
std::vector<HLSLVertexAttributeRemap> remap_vertex_attributes;
|
||||
SmallVector<HLSLVertexAttributeRemap> remap_vertex_attributes;
|
||||
|
||||
uint32_t type_to_consumed_locations(const SPIRType &type) const;
|
||||
|
||||
@ -220,8 +219,8 @@ private:
|
||||
|
||||
// Custom root constant layout, which should be emitted
|
||||
// when translating push constant ranges.
|
||||
std::vector<RootConstants> root_constants_layout;
|
||||
SmallVector<RootConstants> root_constants_layout;
|
||||
};
|
||||
} // namespace spirv_cross
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -30,7 +30,7 @@ static const uint32_t k_unknown_component = ~0u;
|
||||
|
||||
static const uint32_t k_aux_mbr_idx_swizzle_const = 0u;
|
||||
|
||||
CompilerMSL::CompilerMSL(vector<uint32_t> spirv_)
|
||||
CompilerMSL::CompilerMSL(SmallVector<uint32_t> spirv_)
|
||||
: CompilerGLSL(move(spirv_))
|
||||
{
|
||||
}
|
||||
@ -423,7 +423,7 @@ void CompilerMSL::emit_entry_point_declarations()
|
||||
if (type.basetype == SPIRType::Sampler)
|
||||
add_resource_name(samp.first);
|
||||
|
||||
vector<string> args;
|
||||
SmallVector<string> args;
|
||||
auto &s = samp.second;
|
||||
|
||||
if (s.coord != MSL_SAMPLER_COORD_NORMALIZED)
|
||||
@ -659,7 +659,7 @@ string CompilerMSL::compile()
|
||||
next_metal_resource_index_sampler = 0;
|
||||
|
||||
// Move constructor for this type is broken on GCC 4.9 ...
|
||||
buffer = unique_ptr<ostringstream>(new ostringstream());
|
||||
buffer.reset();
|
||||
|
||||
emit_header();
|
||||
emit_specialization_constants_and_structs();
|
||||
@ -670,7 +670,7 @@ string CompilerMSL::compile()
|
||||
pass_count++;
|
||||
} while (is_forcing_recompilation());
|
||||
|
||||
return buffer->str();
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
// Register the need to output any custom functions.
|
||||
@ -1822,7 +1822,7 @@ void CompilerMSL::fix_up_interface_member_indices(StorageClass storage, uint32_t
|
||||
uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
|
||||
{
|
||||
// Accumulate the variables that should appear in the interface struct
|
||||
vector<SPIRVariable *> vars;
|
||||
SmallVector<SPIRVariable *> vars;
|
||||
bool incl_builtins = (storage == StorageClassOutput || is_tessellation_shader());
|
||||
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t var_id, SPIRVariable &var) {
|
||||
@ -2954,8 +2954,8 @@ void CompilerMSL::emit_specialization_constants_and_structs()
|
||||
// TODO: This can be expressed as a [[threads_per_threadgroup]] input semantic, but we need to know
|
||||
// the work group size at compile time in SPIR-V, and [[threads_per_threadgroup]] would need to be passed around as a global.
|
||||
// The work group size may be a specialization constant.
|
||||
statement("constant uint3 ", builtin_to_glsl(BuiltInWorkgroupSize, StorageClassWorkgroup), " [[maybe_unused]] = ",
|
||||
constant_expression(get<SPIRConstant>(workgroup_size_id)), ";");
|
||||
statement("constant uint3 ", builtin_to_glsl(BuiltInWorkgroupSize, StorageClassWorkgroup),
|
||||
" [[maybe_unused]] = ", constant_expression(get<SPIRConstant>(workgroup_size_id)), ";");
|
||||
emitted = true;
|
||||
}
|
||||
else if (c.specialization)
|
||||
@ -3082,7 +3082,7 @@ bool CompilerMSL::emit_tessellation_access_chain(const uint32_t *ops, uint32_t l
|
||||
get_variable_data_type(*var).basetype == SPIRType::Struct))
|
||||
{
|
||||
AccessChainMeta meta;
|
||||
std::vector<uint32_t> indices;
|
||||
SmallVector<uint32_t> indices;
|
||||
uint32_t next_id = ir.increase_bound_by(2);
|
||||
|
||||
indices.reserve(length - 3 + 1);
|
||||
@ -5692,7 +5692,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
|
||||
uint32_t index;
|
||||
};
|
||||
|
||||
vector<Resource> resources;
|
||||
SmallVector<Resource> resources;
|
||||
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
|
||||
if ((var.storage == StorageClassUniform || var.storage == StorageClassUniformConstant ||
|
||||
@ -7408,7 +7408,7 @@ void CompilerMSL::MemberSorter::sort()
|
||||
// Create a temporary array of consecutive member indices and sort it based on how
|
||||
// the members should be reordered, based on builtin and sorting aspect meta info.
|
||||
size_t mbr_cnt = type.member_types.size();
|
||||
vector<uint32_t> mbr_idxs(mbr_cnt);
|
||||
SmallVector<uint32_t> mbr_idxs(mbr_cnt);
|
||||
iota(mbr_idxs.begin(), mbr_idxs.end(), 0); // Fill with consecutive indices
|
||||
std::sort(mbr_idxs.begin(), mbr_idxs.end(), *this); // Sort member indices based on sorting aspect
|
||||
|
||||
@ -7602,7 +7602,7 @@ void CompilerMSL::analyze_argument_buffers()
|
||||
SPIRType::BaseType basetype;
|
||||
uint32_t index;
|
||||
};
|
||||
vector<Resource> resources_in_set[kMaxArgumentBuffers];
|
||||
SmallVector<Resource> resources_in_set[kMaxArgumentBuffers];
|
||||
|
||||
ir.for_each_typed_id<SPIRVariable>([&](uint32_t self, SPIRVariable &var) {
|
||||
if ((var.storage == StorageClassUniform || var.storage == StorageClassUniformConstant ||
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace SPIRV_CROSS_NAMESPACE
|
||||
{
|
||||
@ -268,7 +267,7 @@ public:
|
||||
return capture_output_to_buffer && stage_in_var_id != 0;
|
||||
}
|
||||
|
||||
explicit CompilerMSL(std::vector<uint32_t> spirv);
|
||||
explicit CompilerMSL(SmallVector<uint32_t> spirv);
|
||||
CompilerMSL(const uint32_t *ir, size_t word_count);
|
||||
explicit CompilerMSL(const ParsedIR &ir);
|
||||
explicit CompilerMSL(ParsedIR &&ir);
|
||||
@ -495,9 +494,9 @@ protected:
|
||||
std::unordered_map<MSLStructMemberKey, uint32_t> struct_member_padding;
|
||||
std::set<std::string> pragma_lines;
|
||||
std::set<std::string> typedef_lines;
|
||||
std::vector<uint32_t> vars_needing_early_declaration;
|
||||
SmallVector<uint32_t> vars_needing_early_declaration;
|
||||
|
||||
std::vector<std::pair<MSLResourceBinding, bool>> resource_bindings;
|
||||
SmallVector<std::pair<MSLResourceBinding, bool>> resource_bindings;
|
||||
uint32_t next_metal_resource_index_buffer = 0;
|
||||
uint32_t next_metal_resource_index_texture = 0;
|
||||
uint32_t next_metal_resource_index_sampler = 0;
|
||||
@ -530,7 +529,7 @@ protected:
|
||||
spv::Op previous_instruction_opcode = spv::OpNop;
|
||||
|
||||
std::unordered_map<uint32_t, MSLConstexprSampler> constexpr_samplers;
|
||||
std::vector<uint32_t> buffer_arrays;
|
||||
SmallVector<uint32_t> buffer_arrays;
|
||||
|
||||
uint32_t argument_buffer_ids[kMaxArgumentBuffers];
|
||||
uint32_t argument_buffer_discrete_mask = 0;
|
||||
@ -597,6 +596,6 @@ protected:
|
||||
SortAspect sort_aspect;
|
||||
};
|
||||
};
|
||||
} // namespace spirv_cross
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -22,14 +22,14 @@ using namespace spv;
|
||||
|
||||
namespace SPIRV_CROSS_NAMESPACE
|
||||
{
|
||||
Parser::Parser(std::vector<uint32_t> spirv)
|
||||
Parser::Parser(SmallVector<uint32_t> spirv)
|
||||
{
|
||||
ir.spirv = move(spirv);
|
||||
}
|
||||
|
||||
Parser::Parser(const uint32_t *spirv_data, size_t word_count)
|
||||
{
|
||||
ir.spirv = vector<uint32_t>(spirv_data, spirv_data + word_count);
|
||||
ir.spirv = SmallVector<uint32_t>(spirv_data, spirv_data + word_count);
|
||||
}
|
||||
|
||||
static bool decoration_is_string(Decoration decoration)
|
||||
@ -88,7 +88,7 @@ void Parser::parse()
|
||||
|
||||
uint32_t offset = 5;
|
||||
|
||||
vector<Instruction> instructions;
|
||||
SmallVector<Instruction> instructions;
|
||||
while (offset < len)
|
||||
{
|
||||
Instruction instr = {};
|
||||
@ -131,7 +131,7 @@ const uint32_t *Parser::stream(const Instruction &instr) const
|
||||
return &ir.spirv[instr.offset];
|
||||
}
|
||||
|
||||
static string extract_string(const vector<uint32_t> &spirv, uint32_t offset)
|
||||
static string extract_string(const SmallVector<uint32_t> &spirv, uint32_t offset)
|
||||
{
|
||||
string ret;
|
||||
for (uint32_t i = offset; i < spirv.size(); i++)
|
||||
@ -1097,7 +1097,7 @@ void Parser::make_constant_null(uint32_t id, uint32_t type)
|
||||
if (!constant_type.array_size_literal.back())
|
||||
SPIRV_CROSS_THROW("Array size of OpConstantNull must be a literal.");
|
||||
|
||||
vector<uint32_t> elements(constant_type.array.back());
|
||||
SmallVector<uint32_t> elements(constant_type.array.back());
|
||||
for (uint32_t i = 0; i < constant_type.array.back(); i++)
|
||||
elements[i] = parent_id;
|
||||
set<SPIRConstant>(id, type, elements.data(), uint32_t(elements.size()), false);
|
||||
@ -1105,7 +1105,7 @@ void Parser::make_constant_null(uint32_t id, uint32_t type)
|
||||
else if (!constant_type.member_types.empty())
|
||||
{
|
||||
uint32_t member_ids = ir.increase_bound_by(uint32_t(constant_type.member_types.size()));
|
||||
vector<uint32_t> elements(constant_type.member_types.size());
|
||||
SmallVector<uint32_t> elements(constant_type.member_types.size());
|
||||
for (uint32_t i = 0; i < constant_type.member_types.size(); i++)
|
||||
{
|
||||
make_constant_null(member_ids + i, constant_type.member_types[i]);
|
||||
@ -1120,4 +1120,4 @@ void Parser::make_constant_null(uint32_t id, uint32_t type)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace spirv_cross
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
#include "spirv_cross_parsed_ir.hpp"
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
namespace SPIRV_CROSS_NAMESPACE
|
||||
{
|
||||
@ -27,7 +26,7 @@ class Parser
|
||||
{
|
||||
public:
|
||||
Parser(const uint32_t *spirv_data, size_t word_count);
|
||||
Parser(std::vector<uint32_t> spirv);
|
||||
Parser(SmallVector<uint32_t> spirv);
|
||||
|
||||
void parse();
|
||||
|
||||
@ -84,12 +83,12 @@ private:
|
||||
}
|
||||
|
||||
// This must be an ordered data structure so we always pick the same type aliases.
|
||||
std::vector<uint32_t> global_struct_cache;
|
||||
SmallVector<uint32_t> global_struct_cache;
|
||||
|
||||
bool types_are_logically_equivalent(const SPIRType &a, const SPIRType &b) const;
|
||||
bool variable_storage_is_aliased(const SPIRVariable &v) const;
|
||||
void make_constant_null(uint32_t id, uint32_t type);
|
||||
};
|
||||
} // namespace spirv_cross
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
@ -36,10 +36,16 @@ using Stack = std::stack<State>;
|
||||
class Stream
|
||||
{
|
||||
Stack stack;
|
||||
std::ostringstream buffer;
|
||||
StringStream<> buffer;
|
||||
uint32_t indent{ 0 };
|
||||
char current_locale_radix_character = '.';
|
||||
|
||||
public:
|
||||
void set_current_locale_radix_character(char c)
|
||||
{
|
||||
current_locale_radix_character = c;
|
||||
}
|
||||
|
||||
void begin_json_object();
|
||||
void end_json_object();
|
||||
void emit_json_key(const std::string &key);
|
||||
@ -212,7 +218,7 @@ void Stream::emit_json_key_value(const std::string &key, int32_t value)
|
||||
void Stream::emit_json_key_value(const std::string &key, float value)
|
||||
{
|
||||
emit_json_key(key);
|
||||
statement_inner(value);
|
||||
statement_inner(convert_to_string(value, current_locale_radix_character));
|
||||
}
|
||||
|
||||
void Stream::emit_json_key_value(const std::string &key, bool value)
|
||||
@ -247,8 +253,8 @@ void CompilerReflection::set_format(const std::string &format)
|
||||
|
||||
string CompilerReflection::compile()
|
||||
{
|
||||
// Move constructor for this type is broken on GCC 4.9 ...
|
||||
json_stream = std::make_shared<simple_json::Stream>();
|
||||
json_stream->set_current_locale_radix_character(current_locale_radix_character);
|
||||
json_stream->begin_json_object();
|
||||
emit_entry_points();
|
||||
emit_types();
|
||||
@ -439,7 +445,7 @@ void CompilerReflection::emit_resources()
|
||||
emit_resources("acceleration_structures", res.acceleration_structures);
|
||||
}
|
||||
|
||||
void CompilerReflection::emit_resources(const char *tag, const vector<Resource> &resources)
|
||||
void CompilerReflection::emit_resources(const char *tag, const SmallVector<Resource> &resources)
|
||||
{
|
||||
if (resources.empty())
|
||||
{
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
#include "spirv_glsl.hpp"
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace simple_json
|
||||
{
|
||||
@ -33,8 +32,8 @@ class CompilerReflection : public CompilerGLSL
|
||||
using Parent = CompilerGLSL;
|
||||
|
||||
public:
|
||||
explicit CompilerReflection(std::vector<uint32_t> spirv_)
|
||||
: Parent(move(spirv_))
|
||||
explicit CompilerReflection(SmallVector<uint32_t> spirv_)
|
||||
: Parent(std::move(spirv_))
|
||||
{
|
||||
options.vulkan_semantics = true;
|
||||
}
|
||||
@ -72,13 +71,13 @@ private:
|
||||
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 std::vector<Resource> &resources);
|
||||
void emit_resources(const char *tag, const SmallVector<Resource> &resources);
|
||||
|
||||
std::string to_member_name(const SPIRType &type, uint32_t index) const;
|
||||
|
||||
std::shared_ptr<simple_json::Stream> json_stream;
|
||||
};
|
||||
|
||||
} // namespace spirv_cross
|
||||
} // namespace SPIRV_CROSS_NAMESPACE
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user