diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/spirv_cross/barrier.hpp | 90 | ||||
-rw-r--r-- | include/spirv_cross/external_interface.h | 94 | ||||
-rw-r--r-- | include/spirv_cross/image.hpp | 25 | ||||
-rw-r--r-- | include/spirv_cross/internal_interface.hpp | 964 | ||||
-rw-r--r-- | include/spirv_cross/sampler.hpp | 136 | ||||
-rw-r--r-- | include/spirv_cross/thread_group.hpp | 159 |
6 files changed, 773 insertions, 695 deletions
diff --git a/include/spirv_cross/barrier.hpp b/include/spirv_cross/barrier.hpp index 5d882302..0d77b862 100644 --- a/include/spirv_cross/barrier.hpp +++ b/include/spirv_cross/barrier.hpp @@ -22,58 +22,58 @@ namespace spirv_cross { - class Barrier - { - public: - Barrier() - { - count.store(0); - iteration.store(0); - } +class Barrier +{ +public: + Barrier() + { + count.store(0); + iteration.store(0); + } - void set_release_divisor(unsigned divisor) - { - this->divisor = divisor; - } + void set_release_divisor(unsigned divisor) + { + this->divisor = divisor; + } - static inline void memoryBarrier() - { - std::atomic_thread_fence(std::memory_order_seq_cst); - } + static inline void memoryBarrier() + { + std::atomic_thread_fence(std::memory_order_seq_cst); + } - void reset_counter() - { - count.store(0); - iteration.store(0); - } + void reset_counter() + { + count.store(0); + iteration.store(0); + } - void wait() - { - unsigned target_iteration = iteration.load(std::memory_order_relaxed) + 1; - // Overflows cleanly. - unsigned target_count = divisor * target_iteration; + void wait() + { + unsigned target_iteration = iteration.load(std::memory_order_relaxed) + 1; + // Overflows cleanly. + unsigned target_count = divisor * target_iteration; - // Barriers don't enforce memory ordering. - // Be as relaxed about the barrier as we possibly can! - unsigned c = count.fetch_add(1u, std::memory_order_relaxed); + // Barriers don't enforce memory ordering. + // Be as relaxed about the barrier as we possibly can! + unsigned c = count.fetch_add(1u, std::memory_order_relaxed); - if (c + 1 == target_count) - { - iteration.store(target_iteration, std::memory_order_relaxed); - } - else - { - // If we have more threads than the CPU, don't hog the CPU for very long periods of time. - while (iteration.load(std::memory_order_relaxed) != target_iteration) - std::this_thread::yield(); - } - } + if (c + 1 == target_count) + { + iteration.store(target_iteration, std::memory_order_relaxed); + } + else + { + // If we have more threads than the CPU, don't hog the CPU for very long periods of time. + while (iteration.load(std::memory_order_relaxed) != target_iteration) + std::this_thread::yield(); + } + } - private: - unsigned divisor = 1; - std::atomic<unsigned> count; - std::atomic<unsigned> iteration; - }; +private: + unsigned divisor = 1; + std::atomic<unsigned> count; + std::atomic<unsigned> iteration; +}; } #endif diff --git a/include/spirv_cross/external_interface.h b/include/spirv_cross/external_interface.h index 666aae78..a0067fc1 100644 --- a/include/spirv_cross/external_interface.h +++ b/include/spirv_cross/external_interface.h @@ -27,42 +27,33 @@ typedef struct spirv_cross_shader spirv_cross_shader_t; struct spirv_cross_interface { - spirv_cross_shader_t* (*construct)(void); - void (*destruct)(spirv_cross_shader_t *thiz); - void (*invoke)(spirv_cross_shader_t *thiz); + spirv_cross_shader_t *(*construct)(void); + void (*destruct)(spirv_cross_shader_t *thiz); + void (*invoke)(spirv_cross_shader_t *thiz); }; -void spirv_cross_set_stage_input(spirv_cross_shader_t *thiz, - unsigned location, void *data, size_t size); +void spirv_cross_set_stage_input(spirv_cross_shader_t *thiz, unsigned location, void *data, size_t size); -void spirv_cross_set_stage_output(spirv_cross_shader_t *thiz, - unsigned location, void *data, size_t size); +void spirv_cross_set_stage_output(spirv_cross_shader_t *thiz, unsigned location, void *data, size_t size); -void spirv_cross_set_push_constant(spirv_cross_shader_t *thiz, - void *data, size_t size); +void spirv_cross_set_push_constant(spirv_cross_shader_t *thiz, void *data, size_t size); -void spirv_cross_set_uniform_constant(spirv_cross_shader_t *thiz, - unsigned location, - void *data, size_t size); +void spirv_cross_set_uniform_constant(spirv_cross_shader_t *thiz, unsigned location, void *data, size_t size); -void spirv_cross_set_resource(spirv_cross_shader_t *thiz, - unsigned set, unsigned binding, - void **data, size_t size); +void spirv_cross_set_resource(spirv_cross_shader_t *thiz, unsigned set, unsigned binding, void **data, size_t size); -const struct spirv_cross_interface* spirv_cross_get_interface(void); +const struct spirv_cross_interface *spirv_cross_get_interface(void); typedef enum spirv_cross_builtin { - SPIRV_CROSS_BUILTIN_POSITION = 0, - SPIRV_CROSS_BUILTIN_FRAG_COORD = 1, - SPIRV_CROSS_BUILTIN_WORK_GROUP_ID = 2, - SPIRV_CROSS_BUILTIN_NUM_WORK_GROUPS = 3, - SPIRV_CROSS_NUM_BUILTINS + SPIRV_CROSS_BUILTIN_POSITION = 0, + SPIRV_CROSS_BUILTIN_FRAG_COORD = 1, + SPIRV_CROSS_BUILTIN_WORK_GROUP_ID = 2, + SPIRV_CROSS_BUILTIN_NUM_WORK_GROUPS = 3, + SPIRV_CROSS_NUM_BUILTINS } spirv_cross_builtin; -void spirv_cross_set_builtin(spirv_cross_shader_t *thiz, - spirv_cross_builtin builtin, - void *data, size_t size); +void spirv_cross_set_builtin(spirv_cross_shader_t *thiz, spirv_cross_builtin builtin, void *data, size_t size); #define SPIRV_CROSS_NUM_DESCRIPTOR_SETS 4 #define SPIRV_CROSS_NUM_DESCRIPTOR_BINDINGS 16 @@ -72,64 +63,63 @@ void spirv_cross_set_builtin(spirv_cross_shader_t *thiz, enum spirv_cross_format { - SPIRV_CROSS_FORMAT_R8_UNORM = 0, - SPIRV_CROSS_FORMAT_R8G8_UNORM = 1, - SPIRV_CROSS_FORMAT_R8G8B8_UNORM = 2, - SPIRV_CROSS_FORMAT_R8G8B8A8_UNORM = 3, + SPIRV_CROSS_FORMAT_R8_UNORM = 0, + SPIRV_CROSS_FORMAT_R8G8_UNORM = 1, + SPIRV_CROSS_FORMAT_R8G8B8_UNORM = 2, + SPIRV_CROSS_FORMAT_R8G8B8A8_UNORM = 3, - SPIRV_CROSS_NUM_FORMATS + SPIRV_CROSS_NUM_FORMATS }; enum spirv_cross_wrap { - SPIRV_CROSS_WRAP_CLAMP_TO_EDGE = 0, - SPIRV_CROSS_WRAP_REPEAT = 1, + SPIRV_CROSS_WRAP_CLAMP_TO_EDGE = 0, + SPIRV_CROSS_WRAP_REPEAT = 1, - SPIRV_CROSS_NUM_WRAP + SPIRV_CROSS_NUM_WRAP }; enum spirv_cross_filter { - SPIRV_CROSS_FILTER_NEAREST = 0, - SPIRV_CROSS_FILTER_LINEAR = 1, + SPIRV_CROSS_FILTER_NEAREST = 0, + SPIRV_CROSS_FILTER_LINEAR = 1, - SPIRV_CROSS_NUM_FILTER + SPIRV_CROSS_NUM_FILTER }; enum spirv_cross_mipfilter { - SPIRV_CROSS_MIPFILTER_BASE = 0, - SPIRV_CROSS_MIPFILTER_NEAREST = 1, - SPIRV_CROSS_MIPFILTER_LINEAR = 2, + SPIRV_CROSS_MIPFILTER_BASE = 0, + SPIRV_CROSS_MIPFILTER_NEAREST = 1, + SPIRV_CROSS_MIPFILTER_LINEAR = 2, - SPIRV_CROSS_NUM_MIPFILTER + SPIRV_CROSS_NUM_MIPFILTER }; struct spirv_cross_miplevel { - const void *data; - unsigned width, height; - size_t stride; + const void *data; + unsigned width, height; + size_t stride; }; struct spirv_cross_sampler_info { - const struct spirv_cross_miplevel *mipmaps; - unsigned num_mipmaps; - - enum spirv_cross_format format; - enum spirv_cross_wrap wrap_s; - enum spirv_cross_wrap wrap_t; - enum spirv_cross_filter min_filter; - enum spirv_cross_filter mag_filter; - enum spirv_cross_mipfilter mip_filter; + const struct spirv_cross_miplevel *mipmaps; + unsigned num_mipmaps; + + enum spirv_cross_format format; + enum spirv_cross_wrap wrap_s; + enum spirv_cross_wrap wrap_t; + enum spirv_cross_filter min_filter; + enum spirv_cross_filter mag_filter; + enum spirv_cross_mipfilter mip_filter; }; typedef struct spirv_cross_sampler_2d spirv_cross_sampler_2d_t; spirv_cross_sampler_2d_t *spirv_cross_create_sampler_2d(const struct spirv_cross_sampler_info *info); void spirv_cross_destroy_sampler_2d(spirv_cross_sampler_2d_t *samp); - #ifdef __cplusplus } #endif diff --git a/include/spirv_cross/image.hpp b/include/spirv_cross/image.hpp index 342faf31..1216f117 100644 --- a/include/spirv_cross/image.hpp +++ b/include/spirv_cross/image.hpp @@ -29,17 +29,22 @@ namespace spirv_cross { - template<typename T> - struct image2DBase - { - virtual ~image2DBase() = default; - inline virtual T load(glm::ivec2 coord) { return T(0, 0, 0, 1); } - inline virtual void store(glm::ivec2 coord, const T &v) {} - }; +template <typename T> +struct image2DBase +{ + virtual ~image2DBase() = default; + inline virtual T load(glm::ivec2 coord) + { + return T(0, 0, 0, 1); + } + inline virtual void store(glm::ivec2 coord, const T &v) + { + } +}; - typedef image2DBase<glm::vec4> image2D; - typedef image2DBase<glm::ivec4> iimage2D; - typedef image2DBase<glm::uvec4> uimage2D; +typedef image2DBase<glm::vec4> image2D; +typedef image2DBase<glm::ivec4> iimage2D; +typedef image2DBase<glm::uvec4> uimage2D; } #endif diff --git a/include/spirv_cross/internal_interface.hpp b/include/spirv_cross/internal_interface.hpp index b47ee02b..c3cbdcd5 100644 --- a/include/spirv_cross/internal_interface.hpp +++ b/include/spirv_cross/internal_interface.hpp @@ -39,493 +39,565 @@ namespace internal { - // Adaptor helpers to adapt GLSL access chain syntax to C++. - // Don't bother with arrays of arrays on uniforms ... - // Would likely need horribly complex variadic template munging. - - template<typename T> - struct Interface - { - enum { ArraySize = 1, Size = sizeof(T) }; - - Interface() : ptr(0) {} - T& get() - { - assert(ptr); - return *ptr; - } - - T *ptr; - }; - - // For array types, return a pointer instead. - template<typename T, unsigned U> - struct Interface<T[U]> - { - enum { ArraySize = U, Size = U * sizeof(T) }; - - Interface() : ptr(0) {} - T* get() - { - assert(ptr); - return ptr; - } - - T *ptr; - }; - - // For case when array size is 1, avoid double dereference. - template<typename T> - struct PointerInterface - { - enum { ArraySize = 1, Size = sizeof(T*) }; - enum { PreDereference = true }; - - PointerInterface() : ptr(0) {} - - T& get() - { - assert(ptr); - return *ptr; - } - - T *ptr; - }; - - // Automatically converts a pointer down to reference to match GLSL syntax. - template<typename T> - struct DereferenceAdaptor - { - DereferenceAdaptor(T **ptr) : ptr(ptr) {} - T& operator[](unsigned index) const { return *(ptr[index]); } - T **ptr; - }; - - // We can't have a linear array of T* since T* can be an abstract type in case of samplers. - // We also need a list of pointers since we can have run-time length SSBOs. - template<typename T, unsigned U> - struct PointerInterface<T[U]> - { - enum { ArraySize = U, Size = sizeof(T*) * U }; - enum { PreDereference = false }; - PointerInterface() : ptr(0) {} - - DereferenceAdaptor<T> get() - { - assert(ptr); - return DereferenceAdaptor<T>(ptr); - } - - T **ptr; - }; - - // Resources can be more abstract and be unsized, - // so we need to have an array of pointers for those cases. - template<typename T> struct Resource : PointerInterface<T> {}; - - // POD with no unknown sizes, so we can express these as flat arrays. - template<typename T> struct UniformConstant : Interface<T> {}; - template<typename T> struct StageInput : Interface<T> {}; - template<typename T> struct StageOutput : Interface<T> {}; - template<typename T> struct PushConstant : Interface<T> {}; +// Adaptor helpers to adapt GLSL access chain syntax to C++. +// Don't bother with arrays of arrays on uniforms ... +// Would likely need horribly complex variadic template munging. + +template <typename T> +struct Interface +{ + enum + { + ArraySize = 1, + Size = sizeof(T) + }; + + Interface() + : ptr(0) + { + } + T &get() + { + assert(ptr); + return *ptr; + } + + T *ptr; +}; + +// For array types, return a pointer instead. +template <typename T, unsigned U> +struct Interface<T[U]> +{ + enum + { + ArraySize = U, + Size = U * sizeof(T) + }; + + Interface() + : ptr(0) + { + } + T *get() + { + assert(ptr); + return ptr; + } + + T *ptr; +}; + +// For case when array size is 1, avoid double dereference. +template <typename T> +struct PointerInterface +{ + enum + { + ArraySize = 1, + Size = sizeof(T *) + }; + enum + { + PreDereference = true + }; + + PointerInterface() + : ptr(0) + { + } + + T &get() + { + assert(ptr); + return *ptr; + } + + T *ptr; +}; + +// Automatically converts a pointer down to reference to match GLSL syntax. +template <typename T> +struct DereferenceAdaptor +{ + DereferenceAdaptor(T **ptr) + : ptr(ptr) + { + } + T &operator[](unsigned index) const + { + return *(ptr[index]); + } + T **ptr; +}; + +// We can't have a linear array of T* since T* can be an abstract type in case of samplers. +// We also need a list of pointers since we can have run-time length SSBOs. +template <typename T, unsigned U> +struct PointerInterface<T[U]> +{ + enum + { + ArraySize = U, + Size = sizeof(T *) * U + }; + enum + { + PreDereference = false + }; + PointerInterface() + : ptr(0) + { + } + + DereferenceAdaptor<T> get() + { + assert(ptr); + return DereferenceAdaptor<T>(ptr); + } + + T **ptr; +}; + +// Resources can be more abstract and be unsized, +// so we need to have an array of pointers for those cases. +template <typename T> +struct Resource : PointerInterface<T> +{ +}; + +// POD with no unknown sizes, so we can express these as flat arrays. +template <typename T> +struct UniformConstant : Interface<T> +{ +}; +template <typename T> +struct StageInput : Interface<T> +{ +}; +template <typename T> +struct StageOutput : Interface<T> +{ +}; +template <typename T> +struct PushConstant : Interface<T> +{ +}; } struct spirv_cross_shader { - struct PPSize - { - PPSize() : ptr(0), size(0) {} - void **ptr; - size_t size; - }; - - struct PPSizeResource - { - PPSizeResource() : ptr(0), size(0), pre_dereference(false) {} - void **ptr; - size_t size; - bool pre_dereference; - }; - - PPSizeResource resources[SPIRV_CROSS_NUM_DESCRIPTOR_SETS][SPIRV_CROSS_NUM_DESCRIPTOR_BINDINGS]; - PPSize stage_inputs[SPIRV_CROSS_NUM_STAGE_INPUTS]; - PPSize stage_outputs[SPIRV_CROSS_NUM_STAGE_OUTPUTS]; - PPSize uniform_constants[SPIRV_CROSS_NUM_UNIFORM_CONSTANTS]; - PPSize push_constant; - PPSize builtins[SPIRV_CROSS_NUM_BUILTINS]; - - template<typename U> - void register_builtin(spirv_cross_builtin builtin, const U& value) - { - assert(!builtins[builtin].ptr); - - builtins[builtin].ptr = (void**)&value.ptr; - builtins[builtin].size = sizeof(*value.ptr) * U::ArraySize; - } - - void set_builtin(spirv_cross_builtin builtin, void *data, size_t size) - { - assert(builtins[builtin].ptr); - assert(size >= builtins[builtin].size); - - *builtins[builtin].ptr = data; - } - - template<typename U> - void register_resource(const internal::Resource<U> &value, unsigned set, unsigned binding) - { - assert(set < SPIRV_CROSS_NUM_DESCRIPTOR_SETS); - assert(binding < SPIRV_CROSS_NUM_DESCRIPTOR_BINDINGS); - assert(!resources[set][binding].ptr); - - resources[set][binding].ptr = (void**)&value.ptr; - resources[set][binding].size = internal::Resource<U>::Size; - resources[set][binding].pre_dereference = internal::Resource<U>::PreDereference; - } - - template<typename U> - void register_stage_input(const internal::StageInput<U> &value, unsigned location) - { - assert(location < SPIRV_CROSS_NUM_STAGE_INPUTS); - assert(!stage_inputs[location].ptr); - - stage_inputs[location].ptr = (void**)&value.ptr; - stage_inputs[location].size = internal::StageInput<U>::Size; - } - - template<typename U> - void register_stage_output(const internal::StageOutput<U> &value, unsigned location) - { - assert(location < SPIRV_CROSS_NUM_STAGE_OUTPUTS); - assert(!stage_outputs[location].ptr); - - stage_outputs[location].ptr = (void**)&value.ptr; - stage_outputs[location].size = internal::StageOutput<U>::Size; - } - - template<typename U> - void register_uniform_constant(const internal::UniformConstant<U> &value, unsigned location) - { - assert(location < SPIRV_CROSS_NUM_UNIFORM_CONSTANTS); - assert(!uniform_constants[location].ptr); - - uniform_constants[location].ptr = (void**)&value.ptr; - uniform_constants[location].size = internal::UniformConstant<U>::Size; - } - - template<typename U> - void register_push_constant(const internal::PushConstant<U> &value) - { - assert(!push_constant.ptr); - - push_constant.ptr = (void**)&value.ptr; - push_constant.size = internal::PushConstant<U>::Size; - } - - void set_stage_input(unsigned location, void *data, size_t size) - { - assert(location < SPIRV_CROSS_NUM_STAGE_INPUTS); - assert(stage_inputs[location].ptr); - assert(size >= stage_inputs[location].size); - - *stage_inputs[location].ptr = data; - } - - void set_stage_output(unsigned location, void *data, size_t size) - { - assert(location < SPIRV_CROSS_NUM_STAGE_OUTPUTS); - assert(stage_outputs[location].ptr); - assert(size >= stage_outputs[location].size); - - *stage_outputs[location].ptr = data; - } - - void set_uniform_constant(unsigned location, void *data, size_t size) - { - assert(location < SPIRV_CROSS_NUM_UNIFORM_CONSTANTS); - assert(uniform_constants[location].ptr); - assert(size >= uniform_constants[location].size); - - *uniform_constants[location].ptr = data; - } - - void set_push_constant(void *data, size_t size) - { - assert(push_constant.ptr); - assert(size >= push_constant.size); - - *push_constant.ptr = data; - } - - void set_resource(unsigned set, unsigned binding, - void **data, size_t size) - { - assert(set < SPIRV_CROSS_NUM_DESCRIPTOR_SETS); - assert(binding < SPIRV_CROSS_NUM_DESCRIPTOR_BINDINGS); - assert(resources[set][binding].ptr); - assert(size >= resources[set][binding].size); - - // We're using the regular PointerInterface, dereference ahead of time. - if (resources[set][binding].pre_dereference) - *resources[set][binding].ptr = *data; - else - *resources[set][binding].ptr = data; - } + struct PPSize + { + PPSize() + : ptr(0) + , size(0) + { + } + void **ptr; + size_t size; + }; + + struct PPSizeResource + { + PPSizeResource() + : ptr(0) + , size(0) + , pre_dereference(false) + { + } + void **ptr; + size_t size; + bool pre_dereference; + }; + + PPSizeResource resources[SPIRV_CROSS_NUM_DESCRIPTOR_SETS][SPIRV_CROSS_NUM_DESCRIPTOR_BINDINGS]; + PPSize stage_inputs[SPIRV_CROSS_NUM_STAGE_INPUTS]; + PPSize stage_outputs[SPIRV_CROSS_NUM_STAGE_OUTPUTS]; + PPSize uniform_constants[SPIRV_CROSS_NUM_UNIFORM_CONSTANTS]; + PPSize push_constant; + PPSize builtins[SPIRV_CROSS_NUM_BUILTINS]; + + template <typename U> + void register_builtin(spirv_cross_builtin builtin, const U &value) + { + assert(!builtins[builtin].ptr); + + builtins[builtin].ptr = (void **)&value.ptr; + builtins[builtin].size = sizeof(*value.ptr) * U::ArraySize; + } + + void set_builtin(spirv_cross_builtin builtin, void *data, size_t size) + { + assert(builtins[builtin].ptr); + assert(size >= builtins[builtin].size); + + *builtins[builtin].ptr = data; + } + + template <typename U> + void register_resource(const internal::Resource<U> &value, unsigned set, unsigned binding) + { + assert(set < SPIRV_CROSS_NUM_DESCRIPTOR_SETS); + assert(binding < SPIRV_CROSS_NUM_DESCRIPTOR_BINDINGS); + assert(!resources[set][binding].ptr); + + resources[set][binding].ptr = (void **)&value.ptr; + resources[set][binding].size = internal::Resource<U>::Size; + resources[set][binding].pre_dereference = internal::Resource<U>::PreDereference; + } + + template <typename U> + void register_stage_input(const internal::StageInput<U> &value, unsigned location) + { + assert(location < SPIRV_CROSS_NUM_STAGE_INPUTS); + assert(!stage_inputs[location].ptr); + + stage_inputs[location].ptr = (void **)&value.ptr; + stage_inputs[location].size = internal::StageInput<U>::Size; + } + + template <typename U> + void register_stage_output(const internal::StageOutput<U> &value, unsigned location) + { + assert(location < SPIRV_CROSS_NUM_STAGE_OUTPUTS); + assert(!stage_outputs[location].ptr); + + stage_outputs[location].ptr = (void **)&value.ptr; + stage_outputs[location].size = internal::StageOutput<U>::Size; + } + + template <typename U> + void register_uniform_constant(const internal::UniformConstant<U> &value, unsigned location) + { + assert(location < SPIRV_CROSS_NUM_UNIFORM_CONSTANTS); + assert(!uniform_constants[location].ptr); + + uniform_constants[location].ptr = (void **)&value.ptr; + uniform_constants[location].size = internal::UniformConstant<U>::Size; + } + + template <typename U> + void register_push_constant(const internal::PushConstant<U> &value) + { + assert(!push_constant.ptr); + + push_constant.ptr = (void **)&value.ptr; + push_constant.size = internal::PushConstant<U>::Size; + } + + void set_stage_input(unsigned location, void *data, size_t size) + { + assert(location < SPIRV_CROSS_NUM_STAGE_INPUTS); + assert(stage_inputs[location].ptr); + assert(size >= stage_inputs[location].size); + + *stage_inputs[location].ptr = data; + } + + void set_stage_output(unsigned location, void *data, size_t size) + { + assert(location < SPIRV_CROSS_NUM_STAGE_OUTPUTS); + assert(stage_outputs[location].ptr); + assert(size >= stage_outputs[location].size); + + *stage_outputs[location].ptr = data; + } + + void set_uniform_constant(unsigned location, void *data, size_t size) + { + assert(location < SPIRV_CROSS_NUM_UNIFORM_CONSTANTS); + assert(uniform_constants[location].ptr); + assert(size >= uniform_constants[location].size); + + *uniform_constants[location].ptr = data; + } + + void set_push_constant(void *data, size_t size) + { + assert(push_constant.ptr); + assert(size >= push_constant.size); + + *push_constant.ptr = data; + } + + void set_resource(unsigned set, unsigned binding, void **data, size_t size) + { + assert(set < SPIRV_CROSS_NUM_DESCRIPTOR_SETS); + assert(binding < SPIRV_CROSS_NUM_DESCRIPTOR_BINDINGS); + assert(resources[set][binding].ptr); + assert(size >= resources[set][binding].size); + + // We're using the regular PointerInterface, dereference ahead of time. + if (resources[set][binding].pre_dereference) + *resources[set][binding].ptr = *data; + else + *resources[set][binding].ptr = data; + } }; namespace spirv_cross { - template<typename T> - struct BaseShader : spirv_cross_shader - { - void invoke() - { - static_cast<T*>(this)->main(); - } - }; - - struct FragmentResources - { - internal::StageOutput<glm::vec4> gl_FragCoord; - void init(spirv_cross_shader &s) - { - s.register_builtin(SPIRV_CROSS_BUILTIN_FRAG_COORD, gl_FragCoord); - } +template <typename T> +struct BaseShader : spirv_cross_shader +{ + void invoke() + { + static_cast<T *>(this)->main(); + } +}; + +struct FragmentResources +{ + internal::StageOutput<glm::vec4> gl_FragCoord; + void init(spirv_cross_shader &s) + { + s.register_builtin(SPIRV_CROSS_BUILTIN_FRAG_COORD, gl_FragCoord); + } #define gl_FragCoord __res->gl_FragCoord.get() - }; - - template<typename T, typename Res> - struct FragmentShader : BaseShader<FragmentShader<T, Res> > - { - inline void main() - { - impl.main(); - } - - FragmentShader() - { - resources.init(*this); - impl.__res = &resources; - } - - T impl; - Res resources; - }; - - struct VertexResources - { - internal::StageOutput<glm::vec4> gl_Position; - void init(spirv_cross_shader &s) - { - s.register_builtin(SPIRV_CROSS_BUILTIN_POSITION, gl_Position); - } +}; + +template <typename T, typename Res> +struct FragmentShader : BaseShader<FragmentShader<T, Res>> +{ + inline void main() + { + impl.main(); + } + + FragmentShader() + { + resources.init(*this); + impl.__res = &resources; + } + + T impl; + Res resources; +}; + +struct VertexResources +{ + internal::StageOutput<glm::vec4> gl_Position; + void init(spirv_cross_shader &s) + { + s.register_builtin(SPIRV_CROSS_BUILTIN_POSITION, gl_Position); + } #define gl_Position __res->gl_Position.get() - }; - - template<typename T, typename Res> - struct VertexShader : BaseShader<VertexShader<T, Res> > - { - inline void main() - { - impl.main(); - } - - VertexShader() - { - resources.init(*this); - impl.__res = &resources; - } - - T impl; - Res resources; - }; - - struct TessEvaluationResources - { - inline void init(spirv_cross_shader&) {} - }; - - template<typename T, typename Res> - struct TessEvaluationShader : BaseShader<TessEvaluationShader<T, Res> > - { - inline void main() - { - impl.main(); - } - - TessEvaluationShader() - { - resources.init(*this); - impl.__res = &resources; - } - - T impl; - Res resources; - }; - - struct TessControlResources - { - inline void init(spirv_cross_shader&) {} - }; - - template<typename T, typename Res> - struct TessControlShader : BaseShader<TessControlShader<T, Res> > - { - inline void main() - { - impl.main(); - } - - TessControlShader() - { - resources.init(*this); - impl.__res = &resources; - } - - T impl; - Res resources; - }; - - struct GeometryResources - { - inline void init(spirv_cross_shader&) {} - }; - - template<typename T, typename Res> - struct GeometryShader : BaseShader<GeometryShader<T, Res> > - { - inline void main() - { - impl.main(); - } - - GeometryShader() - { - resources.init(*this); - impl.__res = &resources; - } - - T impl; - Res resources; - }; - - struct ComputeResources - { - internal::StageInput<glm::uvec3> gl_WorkGroupID__; - internal::StageInput<glm::uvec3> gl_NumWorkGroups__; - void init(spirv_cross_shader &s) - { - s.register_builtin(SPIRV_CROSS_BUILTIN_WORK_GROUP_ID, gl_WorkGroupID__); - s.register_builtin(SPIRV_CROSS_BUILTIN_NUM_WORK_GROUPS, gl_NumWorkGroups__); - } +}; + +template <typename T, typename Res> +struct VertexShader : BaseShader<VertexShader<T, Res>> +{ + inline void main() + { + impl.main(); + } + + VertexShader() + { + resources.init(*this); + impl.__res = &resources; + } + + T impl; + Res resources; +}; + +struct TessEvaluationResources +{ + inline void init(spirv_cross_shader &) + { + } +}; + +template <typename T, typename Res> +struct TessEvaluationShader : BaseShader<TessEvaluationShader<T, Res>> +{ + inline void main() + { + impl.main(); + } + + TessEvaluationShader() + { + resources.init(*this); + impl.__res = &resources; + } + + T impl; + Res resources; +}; + +struct TessControlResources +{ + inline void init(spirv_cross_shader &) + { + } +}; + +template <typename T, typename Res> +struct TessControlShader : BaseShader<TessControlShader<T, Res>> +{ + inline void main() + { + impl.main(); + } + + TessControlShader() + { + resources.init(*this); + impl.__res = &resources; + } + + T impl; + Res resources; +}; + +struct GeometryResources +{ + inline void init(spirv_cross_shader &) + { + } +}; + +template <typename T, typename Res> +struct GeometryShader : BaseShader<GeometryShader<T, Res>> +{ + inline void main() + { + impl.main(); + } + + GeometryShader() + { + resources.init(*this); + impl.__res = &resources; + } + + T impl; + Res resources; +}; + +struct ComputeResources +{ + internal::StageInput<glm::uvec3> gl_WorkGroupID__; + internal::StageInput<glm::uvec3> gl_NumWorkGroups__; + void init(spirv_cross_shader &s) + { + s.register_builtin(SPIRV_CROSS_BUILTIN_WORK_GROUP_ID, gl_WorkGroupID__); + s.register_builtin(SPIRV_CROSS_BUILTIN_NUM_WORK_GROUPS, gl_NumWorkGroups__); + } #define gl_WorkGroupID __res->gl_WorkGroupID__.get() #define gl_NumWorkGroups __res->gl_NumWorkGroups.get() - Barrier barrier__; + Barrier barrier__; #define barrier() __res->barrier__.wait() - }; +}; - struct ComputePrivateResources - { - uint32_t gl_LocalInvocationIndex__; +struct ComputePrivateResources +{ + uint32_t gl_LocalInvocationIndex__; #define gl_LocalInvocationIndex __priv_res.gl_LocalInvocationIndex__ - glm::uvec3 gl_LocalInvocationID__; + glm::uvec3 gl_LocalInvocationID__; #define gl_LocalInvocationID __priv_res.gl_LocalInvocationID__ - glm::uvec3 gl_GlobalInvocationID__; + glm::uvec3 gl_GlobalInvocationID__; #define gl_GlobalInvocationID __priv_res.gl_GlobalInvocationID__ - }; - - template<typename T, typename Res, unsigned WorkGroupX, unsigned WorkGroupY, unsigned WorkGroupZ> - struct ComputeShader : BaseShader<ComputeShader<T, Res, WorkGroupX, WorkGroupY, WorkGroupZ> > - { - inline void main() - { - resources.barrier__.reset_counter(); - - for (unsigned z = 0; z < WorkGroupZ; z++) - for (unsigned y = 0; y < WorkGroupY; y++) - for (unsigned x = 0; x < WorkGroupX; x++) - impl[z][y][x].__priv_res.gl_GlobalInvocationID__ = - glm::uvec3(WorkGroupX, WorkGroupY, WorkGroupZ) * resources.gl_WorkGroupID__.get() + - glm::uvec3(x, y, z); - - group.run(); - group.wait(); - } - - ComputeShader() - : group(&impl[0][0][0]) - { - resources.init(*this); - resources.barrier__.set_release_divisor(WorkGroupX * WorkGroupY * WorkGroupZ); - - unsigned i = 0; - for (unsigned z = 0; z < WorkGroupZ; z++) - { - for (unsigned y = 0; y < WorkGroupY; y++) - { - for (unsigned x = 0; x < WorkGroupX; x++) - { - impl[z][y][x].__priv_res.gl_LocalInvocationID__ = - glm::uvec3(x, y, z); - impl[z][y][x].__priv_res.gl_LocalInvocationIndex__ = i++; - impl[z][y][x].__res = &resources; - } - } - } - } - - T impl[WorkGroupZ][WorkGroupY][WorkGroupX]; - ThreadGroup<T, WorkGroupX * WorkGroupY * WorkGroupZ> group; - Res resources; - }; - - inline void memoryBarrierShared() { Barrier::memoryBarrier(); } - inline void memoryBarrier() { Barrier::memoryBarrier(); } - // TODO: Rest of the barriers. - - // Atomics - template<typename T> - inline T atomicAdd(T &v, T a) - { - static_assert(sizeof(std::atomic<T>) == sizeof(T), "Cannot cast properly to std::atomic<T>."); - - // We need explicit memory barriers in GLSL to enfore any ordering. - // FIXME: Can we really cast this? There is no other way I think ... - return std::atomic_fetch_add_explicit(reinterpret_cast<std::atomic<T>*>(&v), - a, std::memory_order_relaxed); - } +}; + +template <typename T, typename Res, unsigned WorkGroupX, unsigned WorkGroupY, unsigned WorkGroupZ> +struct ComputeShader : BaseShader<ComputeShader<T, Res, WorkGroupX, WorkGroupY, WorkGroupZ>> +{ + inline void main() + { + resources.barrier__.reset_counter(); + + for (unsigned z = 0; z < WorkGroupZ; z++) + for (unsigned y = 0; y < WorkGroupY; y++) + for (unsigned x = 0; x < WorkGroupX; x++) + impl[z][y][x].__priv_res.gl_GlobalInvocationID__ = + glm::uvec3(WorkGroupX, WorkGroupY, WorkGroupZ) * resources.gl_WorkGroupID__.get() + + glm::uvec3(x, y, z); + + group.run(); + group.wait(); + } + + ComputeShader() + : group(&impl[0][0][0]) + { + resources.init(*this); + resources.barrier__.set_release_divisor(WorkGroupX * WorkGroupY * WorkGroupZ); + + unsigned i = 0; + for (unsigned z = 0; z < WorkGroupZ; z++) + { + for (unsigned y = 0; y < WorkGroupY; y++) + { + for (unsigned x = 0; x < WorkGroupX; x++) + { + impl[z][y][x].__priv_res.gl_LocalInvocationID__ = glm::uvec3(x, y, z); + impl[z][y][x].__priv_res.gl_LocalInvocationIndex__ = i++; + impl[z][y][x].__res = &resources; + } + } + } + } + + T impl[WorkGroupZ][WorkGroupY][WorkGroupX]; + ThreadGroup<T, WorkGroupX * WorkGroupY * WorkGroupZ> group; + Res resources; +}; + +inline void memoryBarrierShared() +{ + Barrier::memoryBarrier(); +} +inline void memoryBarrier() +{ + Barrier::memoryBarrier(); +} +// TODO: Rest of the barriers. + +// Atomics +template <typename T> +inline T atomicAdd(T &v, T a) +{ + static_assert(sizeof(std::atomic<T>) == sizeof(T), "Cannot cast properly to std::atomic<T>."); + + // We need explicit memory barriers in GLSL to enfore any ordering. + // FIXME: Can we really cast this? There is no other way I think ... + return std::atomic_fetch_add_explicit(reinterpret_cast<std::atomic<T> *>(&v), a, std::memory_order_relaxed); +} } void spirv_cross_set_stage_input(spirv_cross_shader_t *shader, unsigned location, void *data, size_t size) { - shader->set_stage_input(location, data, size); + shader->set_stage_input(location, data, size); } void spirv_cross_set_stage_output(spirv_cross_shader_t *shader, unsigned location, void *data, size_t size) { - shader->set_stage_output(location, data, size); + shader->set_stage_output(location, data, size); } void spirv_cross_set_uniform_constant(spirv_cross_shader_t *shader, unsigned location, void *data, size_t size) { - shader->set_uniform_constant(location, data, size); + shader->set_uniform_constant(location, data, size); } void spirv_cross_set_resource(spirv_cross_shader_t *shader, unsigned set, unsigned binding, void **data, size_t size) { - shader->set_resource(set, binding, data, size); + shader->set_resource(set, binding, data, size); } void spirv_cross_set_push_constant(spirv_cross_shader_t *shader, void *data, size_t size) { - shader->set_push_constant(data, size); + shader->set_push_constant(data, size); } -void spirv_cross_set_builtin(spirv_cross_shader_t *shader, spirv_cross_builtin builtin, - void *data, size_t size) +void spirv_cross_set_builtin(spirv_cross_shader_t *shader, spirv_cross_builtin builtin, void *data, size_t size) { - shader->set_builtin(builtin, data, size); + shader->set_builtin(builtin, data, size); } #endif diff --git a/include/spirv_cross/sampler.hpp b/include/spirv_cross/sampler.hpp index ca0aa9d1..e38e569a 100644 --- a/include/spirv_cross/sampler.hpp +++ b/include/spirv_cross/sampler.hpp @@ -21,81 +21,85 @@ namespace spirv_cross { - struct spirv_cross_sampler_2d - { - inline virtual ~spirv_cross_sampler_2d() {} - }; - - template<typename T> - struct sampler2DBase : spirv_cross_sampler_2d - { - sampler2DBase(const spirv_cross_sampler_info *info) - { - mips.insert(mips.end(), info->mipmaps, info->mipmaps + info->num_mipmaps); - format = info->format; - wrap_s = info->wrap_s; - wrap_t = info->wrap_t; - min_filter = info->min_filter; - mag_filter = info->mag_filter; - mip_filter = info->mip_filter; - } +struct spirv_cross_sampler_2d +{ + inline virtual ~spirv_cross_sampler_2d() + { + } +}; - inline virtual T sample(glm::vec2 uv, float bias) - { - return sampleLod(uv, bias); - } +template <typename T> +struct sampler2DBase : spirv_cross_sampler_2d +{ + sampler2DBase(const spirv_cross_sampler_info *info) + { + mips.insert(mips.end(), info->mipmaps, info->mipmaps + info->num_mipmaps); + format = info->format; + wrap_s = info->wrap_s; + wrap_t = info->wrap_t; + min_filter = info->min_filter; + mag_filter = info->mag_filter; + mip_filter = info->mip_filter; + } - inline virtual T sampleLod(glm::vec2 uv, float lod) - { - if (mag_filter == SPIRV_CROSS_FILTER_NEAREST) - { - uv.x = wrap(uv.x, wrap_s, mips[0].width); - uv.y = wrap(uv.y, wrap_t, mips[0].height); - glm::vec2 uv_full = uv * glm::vec2(mips[0].width, mips[0].height); + inline virtual T sample(glm::vec2 uv, float bias) + { + return sampleLod(uv, bias); + } - int x = int(uv_full.x); - int y = int(uv_full.y); - return sample(x, y, 0); - } - else - { - return T(0, 0, 0, 1); - } - } + inline virtual T sampleLod(glm::vec2 uv, float lod) + { + if (mag_filter == SPIRV_CROSS_FILTER_NEAREST) + { + uv.x = wrap(uv.x, wrap_s, mips[0].width); + uv.y = wrap(uv.y, wrap_t, mips[0].height); + glm::vec2 uv_full = uv * glm::vec2(mips[0].width, mips[0].height); - inline float wrap(float v, spirv_cross_wrap wrap, unsigned size) - { - switch (wrap) - { - case SPIRV_CROSS_WRAP_REPEAT: - return v - glm::floor(v); - case SPIRV_CROSS_WRAP_CLAMP_TO_EDGE: - { - float half = 0.5f / size; - return glm::clamp(v, half, 1.0f - half); - } + int x = int(uv_full.x); + int y = int(uv_full.y); + return sample(x, y, 0); + } + else + { + return T(0, 0, 0, 1); + } + } - default: - return 0.0f; - } - } + inline float wrap(float v, spirv_cross_wrap wrap, unsigned size) + { + switch (wrap) + { + case SPIRV_CROSS_WRAP_REPEAT: + return v - glm::floor(v); + case SPIRV_CROSS_WRAP_CLAMP_TO_EDGE: + { + float half = 0.5f / size; + return glm::clamp(v, half, 1.0f - half); + } - std::vector<spirv_cross_miplevel> mips; - spirv_cross_format format; - spirv_cross_wrap wrap_s; - spirv_cross_format wrap_t; - spirv_cross_filter min_filter; - spirv_cross_filter mag_filter; - spirv_cross_mipfilter mip_filter; - }; + default: + return 0.0f; + } + } - typedef sampler2DBase<glm::vec4> sampler2D; - typedef sampler2DBase<glm::ivec4> isampler2D; - typedef sampler2DBase<glm::uvec4> usampler2D; + std::vector<spirv_cross_miplevel> mips; + spirv_cross_format format; + spirv_cross_wrap wrap_s; + spirv_cross_format wrap_t; + spirv_cross_filter min_filter; + spirv_cross_filter mag_filter; + spirv_cross_mipfilter mip_filter; +}; - template<typename T> - inline T texture(const sampler2DBase<T> &samp, const glm::vec2 &uv, float bias = 0.0f) { return samp.sample(uv, bias); } +typedef sampler2DBase<glm::vec4> sampler2D; +typedef sampler2DBase<glm::ivec4> isampler2D; +typedef sampler2DBase<glm::uvec4> usampler2D; +template <typename T> +inline T texture(const sampler2DBase<T> &samp, const glm::vec2 &uv, float bias = 0.0f) +{ + return samp.sample(uv, bias); +} } #endif diff --git a/include/spirv_cross/thread_group.hpp b/include/spirv_cross/thread_group.hpp index 5877d243..81a9bf36 100644 --- a/include/spirv_cross/thread_group.hpp +++ b/include/spirv_cross/thread_group.hpp @@ -23,91 +23,98 @@ namespace spirv_cross { - template<typename T, unsigned Size> - class ThreadGroup - { - public: - ThreadGroup(T *impl) - { - for (unsigned i = 0; i < Size; i++) - workers[i].start(&impl[i]); - } +template <typename T, unsigned Size> +class ThreadGroup +{ +public: + ThreadGroup(T *impl) + { + for (unsigned i = 0; i < Size; i++) + workers[i].start(&impl[i]); + } - void run() - { - for (auto &worker : workers) - worker.run(); - } + void run() + { + for (auto &worker : workers) + worker.run(); + } - void wait() - { - for (auto &worker : workers) - worker.wait(); - } + void wait() + { + for (auto &worker : workers) + worker.wait(); + } - private: - struct Thread - { - enum State - { - Idle, - Running, - Dying - }; - State state = Idle; +private: + struct Thread + { + enum State + { + Idle, + Running, + Dying + }; + State state = Idle; - void start(T *impl) - { - worker = std::thread([impl, this] { - for (;;) - { - { - std::unique_lock<std::mutex> l{lock}; - cond.wait(l, [this] { return state != Idle; }); - if (state == Dying) - break; - } + void start(T *impl) + { + worker = std::thread([impl, this] + { + for (;;) + { + { + std::unique_lock<std::mutex> l{ lock }; + cond.wait(l, [this] + { + return state != Idle; + }); + if (state == Dying) + break; + } - impl->main(); + impl->main(); - std::lock_guard<std::mutex> l{lock}; - state = Idle; - cond.notify_one(); - } - }); - } + std::lock_guard<std::mutex> l{ lock }; + state = Idle; + cond.notify_one(); + } + }); + } - void wait() - { - std::unique_lock<std::mutex> l{lock}; - cond.wait(l, [this] { return state == Idle; }); - } + void wait() + { + std::unique_lock<std::mutex> l{ lock }; + cond.wait(l, [this] + { + return state == Idle; + }); + } - void run() - { - std::lock_guard<std::mutex> l{lock}; - state = Running; - cond.notify_one(); - } + void run() + { + std::lock_guard<std::mutex> l{ lock }; + state = Running; + cond.notify_one(); + } - ~Thread() - { - if (worker.joinable()) - { - { - std::lock_guard<std::mutex> l{lock}; - state = Dying; - cond.notify_one(); - } - worker.join(); - } - } - std::thread worker; - std::condition_variable cond; - std::mutex lock; - }; - Thread workers[Size]; - }; + ~Thread() + { + if (worker.joinable()) + { + { + std::lock_guard<std::mutex> l{ lock }; + state = Dying; + cond.notify_one(); + } + worker.join(); + } + } + std::thread worker; + std::condition_variable cond; + std::mutex lock; + }; + Thread workers[Size]; +}; } #endif |