Compare commits

..
30 Commits
Author SHA1 Message Date
Eliza Velasquez 0709f7d59a stuff 2024-03-06 15:02:15 -08:00
Eliza Velasquez 2027c9e237 stuff 2024-02-28 16:05:28 -08:00
Eliza Velasquez 86456c9e34 swizzle! struct indexing! 2024-02-27 17:04:25 -08:00
Eliza Velasquez fad58ba892 insert room for literal operand expressions 2024-02-27 15:39:40 -08:00
Eliza Velasquez 8ae296974c rename bunch of stuff 2024-02-27 14:31:32 -08:00
Eliza Velasquez f9575675d9 more global symbols 2024-02-27 12:54:41 -08:00
Eliza Velasquez 71025cf25a stringify, flesh out global symbols 2024-02-26 16:54:05 -08:00
Eliza Velasquez a067fb02b1 finish get_if 2024-02-26 14:37:14 -08:00
Eliza Velasquez ffde51ee6f continue eradicating get_if 2024-02-26 13:13:25 -08:00
Eliza Velasquez 35f99ed168 templatify 2024-02-23 15:07:18 -08:00
Eliza Velasquez a939ad03f8 stuff 2024-02-22 17:01:54 -08:00
Eliza Velasquez 05e628fff9 more codegen 2024-02-22 15:52:42 -08:00
Eliza Velasquez ad8473760a start literal value support 2024-02-21 17:09:01 -08:00
Eliza Velasquez cb672eb063 more rigorous glsl code gen 2024-02-21 16:04:20 -08:00
Eliza Velasquez 9811b785cb split locals and globals 2024-02-20 16:40:52 -08:00
Eliza Velasquez ff6d4d721e major refactor 2024-02-20 14:08:07 -08:00
Eliza Velasquez c8a5094c41 stuff 2024-02-16 15:03:53 -08:00
Eliza Velasquez 0f34603cfc stringify stuff 2024-02-14 17:11:24 -08:00
Eliza Velasquez 300f80448d test 2024-02-13 16:58:49 -08:00
Eliza Velasquez a41d343a75 wip: komi 2024-02-12 16:59:06 -08:00
Mathias Agopian 02f5903b67 fix external images
It turns out that many drivers require to rebind the external texture
after its content has changed, so we now always do that.

Bug #6188
2024-01-26 14:17:48 -08:00
Mathias Agopian c39a870abc fix mobile debug builds, missing incluldes 2024-01-26 11:14:16 -08:00
Mathias Agopian 09b8008e17 add missing public headers in backend 2024-01-26 10:58:28 -08:00
Mathias Agopian 59b59cf6be add missing includes in libutils public headers 2024-01-26 10:58:00 -08:00
Mathias Agopian 0df6013263 update remote ui 2024-01-26 10:57:37 -08:00
Mathias Agopian d5041fced7 support execinfo.h on Android 33 and above
Note: this currently requires to compile filament with API_LEVEL 33.
2024-01-25 14:50:29 -08:00
Mathias Agopian 9c54b8a777 fix typo that broke FSR upscaling 2024-01-25 10:34:47 -08:00
Mathias Agopian 8a534d0940 Fix missing/extra includes in all public headers 2024-01-24 23:13:14 -08:00
Mathias Agopian 130825422e Shadowmap texture vizualizer
The vizualizer is implemented inside filament itself and activated
using the debug registry. This intended for filament development use.
2024-01-24 11:28:11 -08:00
Powei Feng 984006ee25 geometry: allow additional attributes in TangentSpaceMesh (#7483)
- Add methods for adding attributes to the input mesh
 - Add method in TangentSpaceMesh for when user provides the
   tangents
 - Separate client-side Algorithm enum from implementation algorithm
   (AlgorithmImpl)
 - Fix CMake config for combining static libs
2024-01-23 16:16:35 -08:00
136 changed files with 5682 additions and 401 deletions
+2 -1
View File
@@ -1,7 +1,8 @@
;;; Directory Local Variables -*- no-byte-compile: t -*-
;;; For more information see (info "(emacs) Directory Variables")
((c++-mode . ((c-file-style . "filament")
((c++-mode . ((eglot-ignored-server-capabilities . (:documentFormattingProvider))
(c-file-style . "filament")
(apheleia-inhibit . t)))
(c-mode . ((c-file-style . "filament")
(apheleia-inhibit . t))))
+6 -3
View File
@@ -634,9 +634,9 @@ function(combine_static_libs TARGET OUTPUT DEPS)
# Loop through the dependent libraries and query their location on disk.
set(DEPS_FILES )
foreach(DEPENDENCY ${DEPS})
if(TARGET ${DEPENDENCY})
if (TARGET ${DEPENDENCY})
get_property(dep_type TARGET ${DEPENDENCY} PROPERTY TYPE)
if(dep_type STREQUAL "STATIC_LIBRARY")
if (dep_type STREQUAL "STATIC_LIBRARY")
list(APPEND DEPS_FILES "$<TARGET_FILE:${DEPENDENCY}>")
endif()
endif()
@@ -721,7 +721,6 @@ add_subdirectory(${LIBRARIES}/filabridge)
add_subdirectory(${LIBRARIES}/filaflat)
add_subdirectory(${LIBRARIES}/filagui)
add_subdirectory(${LIBRARIES}/filameshio)
add_subdirectory(${LIBRARIES}/geometry)
add_subdirectory(${LIBRARIES}/gltfio)
add_subdirectory(${LIBRARIES}/ibl)
add_subdirectory(${LIBRARIES}/iblprefilter)
@@ -749,12 +748,16 @@ add_subdirectory(${EXTERNAL}/jsmn/tnt)
add_subdirectory(${EXTERNAL}/stb/tnt)
add_subdirectory(${EXTERNAL}/getopt)
# Note that this has to be placed after mikktspace in order for combine_static_libs to work.
add_subdirectory(${LIBRARIES}/geometry)
if (FILAMENT_BUILD_FILAMAT OR IS_HOST_PLATFORM)
# spirv-tools must come before filamat, as filamat relies on the presence of the
# spirv-tools_SOURCE_DIR variable.
add_subdirectory(${EXTERNAL}/spirv-tools)
add_subdirectory(${EXTERNAL}/glslang/tnt)
add_subdirectory(${EXTERNAL}/spirv-cross/tnt)
add_subdirectory(${LIBRARIES}/astrict)
add_subdirectory(${LIBRARIES}/filamat)
# the material debugger requires filamat
+2 -2
View File
@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.50.1'
implementation 'com.google.android.filament:filament-android:1.50.0'
}
```
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
iOS projects can use CocoaPods to install the latest release:
```shell
pod 'Filament', '~> 1.50.1'
pod 'Filament', '~> 1.50.0'
```
### Snapshots
+1 -1
View File
@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.50.1
VERSION_NAME=1.50.0
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
File diff suppressed because one or more lines are too long
Binary file not shown.
+1
View File
@@ -238,6 +238,7 @@ set(MATERIAL_SRCS
src/materials/resolveDepth.mat
src/materials/separableGaussianBlur.mat
src/materials/skybox.mat
src/materials/shadowmap.mat
src/materials/ssao/bilateralBlur.mat
src/materials/ssao/bilateralBlurBentNormals.mat
src/materials/ssao/mipmapDepth.mat
@@ -23,7 +23,6 @@
#include <utils/ostream.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
@@ -17,8 +17,6 @@
#ifndef TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
#define TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
#include <utils/compiler.h>
namespace filament::backend {
/**
@@ -28,7 +28,8 @@
#include <math/vec4.h>
#include <array> // FIXME: STL headers are not allowed in public headers
#include <array> // FIXME: STL headers are not allowed in public headers
#include <type_traits> // FIXME: STL headers are not allowed in public headers
#include <stddef.h>
#include <stdint.h>
+4 -6
View File
@@ -17,16 +17,14 @@
#ifndef TNT_FILAMENT_BACKEND_HANDLE_H
#define TNT_FILAMENT_BACKEND_HANDLE_H
#include <utils/compiler.h>
#if !defined(NDEBUG)
#include <utils/Log.h>
#include <utils/ostream.h>
#endif
#include <utils/debug.h>
#include <stdint.h>
#include <type_traits> // FIXME: STL headers are not allowed in public headers
#include <limits>
#include <type_traits>
#include <stdint.h>
namespace filament::backend {
@@ -54,7 +52,7 @@ struct HwVertexBuffer;
class HandleBase {
public:
using HandleId = uint32_t;
static constexpr const HandleId nullid = HandleId{ std::numeric_limits<HandleId>::max() };
static constexpr const HandleId nullid = HandleId{ UINT32_MAX };
constexpr HandleBase() noexcept: object(nullid) {}
@@ -20,7 +20,7 @@
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include <limits>
#include <utils/ostream.h>
#include <stdint.h>
@@ -33,10 +33,7 @@ struct PipelineState {
RasterState rasterState;
StencilState stencilState;
PolygonOffset polygonOffset;
Viewport scissor{ 0, 0,
(uint32_t)std::numeric_limits<int32_t>::max(),
(uint32_t)std::numeric_limits<int32_t>::max()
};
Viewport scissor{ 0, 0, (uint32_t)INT32_MAX, (uint32_t)INT32_MAX };
};
} // namespace filament::backend
@@ -24,6 +24,7 @@
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/ostream.h>
#include <stddef.h>
#include <stdint.h>
+2 -2
View File
@@ -19,11 +19,11 @@
#ifndef TNT_FILAMENT_BACKEND_PLATFORM_H
#define TNT_FILAMENT_BACKEND_PLATFORM_H
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
#include <utils/Invocable.h>
#include <stddef.h>
namespace filament::backend {
class Driver;
@@ -21,8 +21,7 @@
#include <utils/compiler.h>
namespace filament {
namespace backend {
namespace filament::backend {
/**
* A PresentCallable is a callable object that, when called, schedules a frame for presentation on
@@ -98,7 +97,6 @@ private:
*/
using FrameFinishedCallback UTILS_DEPRECATED = void(*)(PresentCallable callable, void* user);
} // namespace backend
} // namespace filament
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_PRESENTCALLABLE
+6 -4
View File
@@ -17,17 +17,19 @@
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_PROGRAM_H
#define TNT_FILAMENT_BACKEND_PRIVATE_PROGRAM_H
#include <utils/compiler.h>
#include <utils/CString.h>
#include <utils/FixedCapacityVector.h>
#include <utils/Invocable.h>
#include <utils/Log.h>
#include <utils/ostream.h>
#include <backend/DriverEnums.h>
#include <array>
#include <variant>
#include <array> // FIXME: STL headers are not allowed in public headers
#include <utility> // FIXME: STL headers are not allowed in public headers
#include <variant> // FIXME: STL headers are not allowed in public headers
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
@@ -24,9 +24,6 @@
#include <utils/compiler.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
struct UTILS_PUBLIC SamplerDescriptor {
@@ -17,9 +17,11 @@
#ifndef TNT_FILAMENT_BACKEND_TARGETBUFFERINFO_H
#define TNT_FILAMENT_BACKEND_TARGETBUFFERINFO_H
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include <utils/ostream.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
@@ -18,8 +18,11 @@
#define TNT_FILAMENT_BACKEND_PRIVATE_OPENGLPLATFORM_H
#include <backend/AcquiredImage.h>
#include <backend/DriverEnums.h>
#include <backend/Platform.h>
#include <stdint.h>
namespace filament::backend {
class Driver;
@@ -17,11 +17,10 @@
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
#include <stdint.h>
#include <backend/DriverEnums.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/DriverEnums.h>
#include <stdint.h>
namespace filament::backend {
@@ -30,7 +30,7 @@ struct PlatformCocoaTouchGLImpl;
class PlatformCocoaTouchGL : public OpenGLPlatform {
public:
PlatformCocoaTouchGL();
~PlatformCocoaTouchGL() noexcept;
~PlatformCocoaTouchGL() noexcept override;
// --------------------------------------------------------------------------------------------
// Platform Interface
@@ -17,18 +17,21 @@
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_H
#include <stdint.h>
#include <backend/DriverEnums.h>
#include <backend/Platform.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglplatform.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/DriverEnums.h>
#include <initializer_list>
#include <utility>
#include <vector>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
/**
@@ -17,8 +17,14 @@
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H
#include <backend/AcquiredImage.h>
#include <backend/Platform.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/platforms/PlatformEGL.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
class ExternalStreamManagerAndroid;
@@ -20,13 +20,18 @@
#include <backend/Platform.h>
#include <bluevk/BlueVK.h>
#include <utils/CString.h>
#include <utils/FixedCapacityVector.h>
#include <utils/PrivateImplementation.h>
#include <string_view>
#include <tuple>
#include <unordered_set>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
using SwapChain = Platform::SwapChain;
@@ -17,10 +17,7 @@
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_CIRCULARBUFFER_H
#define TNT_FILAMENT_BACKEND_PRIVATE_CIRCULARBUFFER_H
#include <utils/compiler.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
@@ -19,12 +19,14 @@
#include "private/backend/CircularBuffer.h"
#include <utils/compiler.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
#include <vector>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
/*
@@ -32,11 +32,13 @@
#include <backend/TargetBufferInfo.h>
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/ThreadUtils.h>
#include <cstddef>
#include <functional>
#include <tuple>
#include <type_traits>
#include <utility>
#ifndef NDEBUG
@@ -152,14 +154,14 @@ struct CommandType<void (Driver::*)(ARGS...)> {
}
// placement new declared as "throw" to avoid the compiler's null-check
inline void* operator new(std::size_t size, void* ptr) {
inline void* operator new(std::size_t, void* ptr) {
assert_invariant(ptr);
return ptr;
}
};
};
// convert an method of "class Driver" into a Command<> type
// convert a method of "class Driver" into a Command<> type
#define COMMAND_TYPE(method) CommandType<decltype(&Driver::method)>::Command<&Driver::method>
// ------------------------------------------------------------------------------------------------
@@ -29,6 +29,7 @@
#include <functional>
#include <stddef.h>
#include <stdint.h>
// Command debugging off. debugging virtuals are not called.
@@ -22,9 +22,18 @@
#include <utils/Allocator.h>
#include <utils/Log.h>
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/ostream.h>
#include <tsl/robin_map.h>
#include <exception>
#include <type_traits>
#include <unordered_map>
#include <stddef.h>
#include <stdint.h>
#if !defined(NDEBUG) && UTILS_HAS_RTTI
# define HANDLE_TYPE_SAFETY 1
#else
@@ -222,7 +231,7 @@ private:
explicit Allocator(const utils::AreaPolicy::HeapArea& area);
// this is in fact always called with a constexpr size argument
[[nodiscard]] inline void* alloc(size_t size, size_t alignment, size_t extra) noexcept {
[[nodiscard]] inline void* alloc(size_t size, size_t, size_t extra) noexcept {
void* p = nullptr;
if (size <= mPool0.getSize()) p = mPool0.alloc(size, 16, extra);
else if (size <= mPool1.getSize()) p = mPool1.alloc(size, 16, extra);
@@ -19,9 +19,9 @@
#ifndef TNT_FILAMENT_BACKEND_PLATFORM_FACTORY_H
#define TNT_FILAMENT_BACKEND_PLATFORM_FACTORY_H
#include "backend/DriverEnums.h"
#include <backend/DriverEnums.h>
#include "utils/compiler.h"
#include <utils/compiler.h>
namespace filament::backend {
@@ -17,15 +17,13 @@
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_SAMPLERGROUP_H
#define TNT_FILAMENT_BACKEND_PRIVATE_SAMPLERGROUP_H
#include "backend/DriverApiForward.h"
#include <utils/compiler.h>
#include <utils/FixedCapacityVector.h>
#include <backend/DriverApiForward.h>
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include <backend/SamplerDescriptor.h>
#include <utils/FixedCapacityVector.h>
#include <utils/ostream.h>
#include <stddef.h>
namespace filament::backend {
+14 -1
View File
@@ -21,7 +21,12 @@
#include <backend/AcquiredImage.h>
#include <backend/BufferDescriptor.h>
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/Log.h>
#include <utils/ostream.h>
#include <utils/Systrace.h>
#include <math/half.h>
@@ -29,6 +34,13 @@
#include <math/vec3.h>
#include <math/vec4.h>
#include <functional>
#include <mutex>
#include <utility>
#include <stddef.h>
#include <stdint.h>
using namespace utils;
using namespace filament::math;
@@ -119,7 +131,8 @@ void DriverBase::purge() noexcept {
// ------------------------------------------------------------------------------------------------
void DriverBase::scheduleDestroySlow(BufferDescriptor&& buffer) noexcept {
scheduleCallback(buffer.getHandler(), [buffer = std::move(buffer)]() {
auto const handler = buffer.getHandler();
scheduleCallback(handler, [buffer = std::move(buffer)]() {
// user callback is called when BufferDescriptor gets destroyed
});
}
@@ -20,6 +20,7 @@
#include "MetalUtils.h"
#include <utils/Panic.h>
#include <utils/Log.h>
namespace filament::backend {
@@ -19,6 +19,7 @@
#include "MetalContext.h"
#include <utils/Panic.h>
#include <utils/Log.h>
#include <utils/trap.h>
#include <thread>
@@ -21,6 +21,7 @@
#include "MetalUtils.h"
#include <utils/Panic.h>
#include <utils/Log.h>
#include <utils/trap.h>
#define NSERROR_CHECK(message) \
+2
View File
@@ -18,6 +18,8 @@
#include "MetalEnums.h"
#include <utils/Log.h>
namespace filament {
namespace backend {
@@ -427,7 +427,6 @@ void OpenGLContext::initBugs(Bugs* bugs, Extensions const& exts,
if (strstr(renderer, "Mali-T")) {
bugs->disable_glFlush = true;
bugs->disable_shared_context_draws = true;
bugs->texture_external_needs_rebind = true;
// We have not verified that timer queries work on Mali-T, so we disable to be safe.
bugs->dont_use_timer_query = true;
}
+1 -8
View File
@@ -222,10 +222,6 @@ public:
// Some drivers have gl state issues when drawing from shared contexts
bool disable_shared_context_draws;
// Some drivers require the GL_TEXTURE_EXTERNAL_OES target to be bound when
// the texture image changes, even if it's already bound to that texture
bool texture_external_needs_rebind;
// Some web browsers seem to immediately clear the default framebuffer when calling
// glInvalidateFramebuffer with WebGL 2.0
bool disable_invalidate_framebuffer;
@@ -433,9 +429,6 @@ private:
{ bugs.disable_shared_context_draws,
"disable_shared_context_draws",
""},
{ bugs.texture_external_needs_rebind,
"texture_external_needs_rebind",
""},
{ bugs.disable_invalidate_framebuffer,
"disable_invalidate_framebuffer",
""},
@@ -711,7 +704,7 @@ void OpenGLContext::bindTexture(GLuint unit, GLuint target, GLuint texId, size_t
update_state(state.textures.units[unit].targets[targetIndex].texture_id, texId, [&]() {
activeTexture(unit);
glBindTexture(target, texId);
}, (target == GL_TEXTURE_EXTERNAL_OES) && bugs.texture_external_needs_rebind);
}, target == GL_TEXTURE_EXTERNAL_OES);
}
void OpenGLContext::bindTexture(GLuint unit, GLuint target, GLuint texId) noexcept {
@@ -15,6 +15,7 @@
*/
#include <backend/platforms/VulkanPlatform.h>
#include <backend/DriverEnums.h>
#include "vulkan/VulkanConstants.h"
#include "vulkan/VulkanDriverFactory.h"
@@ -23,6 +24,11 @@
#include <bluevk/BlueVK.h>
#include <tuple>
#include <stdint.h>
#include <stddef.h>
#if defined(__linux__) || defined(__FreeBSD__)
#define LINUX_OR_FREEBSD 1
#endif
+18 -12
View File
@@ -21,10 +21,14 @@
#include <utils/compiler.h>
#include <limits>
#include <math/mat3.h>
#include <math/mat4.h>
#include <math/vec3.h>
#include <math/vec4.h>
#include <float.h>
#include <stddef.h>
namespace filament {
@@ -70,7 +74,7 @@ public:
* @return This bounding box
*/
Box& set(const math::float3& min, const math::float3& max) noexcept {
// float3 ctor needed for visual studio
// float3 ctor needed for Visual Studio
center = (max + min) * math::float3(0.5f);
halfExtent = (max - min) * math::float3(0.5f);
return *this;
@@ -130,17 +134,17 @@ public:
struct UTILS_PUBLIC Aabb {
/** min coordinates */
math::float3 min = std::numeric_limits<float>::max();
math::float3 min = FLT_MAX;
/** max coordinates */
math::float3 max = std::numeric_limits<float>::lowest();
math::float3 max = -FLT_MAX;
/**
* Computes the center of the box.
* @return (max + min)/2
*/
math::float3 center() const noexcept {
// float3 ctor needed for visual studio
// float3 ctor needed for Visual Studio
return (max + min) * math::float3(0.5f);
}
@@ -149,7 +153,7 @@ struct UTILS_PUBLIC Aabb {
* @return (max - min)/2
*/
math::float3 extent() const noexcept {
// float3 ctor needed for visual studio
// float3 ctor needed for Visual Studio
return (max - min) * math::float3(0.5f);
}
@@ -198,12 +202,14 @@ struct UTILS_PUBLIC Aabb {
* @return the maximum signed distance to the box. Negative if p is in the box
*/
float contains(math::float3 p) const noexcept {
// we don't use std::max to avoid a dependency on <algorithm>
auto const maximum = [](auto a, auto b) { return a > b ? a : b; };
float d = min.x - p.x;
d = std::max(d, min.y - p.y);
d = std::max(d, min.z - p.z);
d = std::max(d, p.x - max.x);
d = std::max(d, p.y - max.y);
d = std::max(d, p.z - max.z);
d = maximum(d, min.y - p.y);
d = maximum(d, min.z - p.z);
d = maximum(d, p.x - max.x);
d = maximum(d, p.y - max.y);
d = maximum(d, p.z - max.z);
return d;
}
+3 -1
View File
@@ -22,11 +22,13 @@
#include <filament/FilamentAPI.h>
#include <backend/DriverEnums.h>
#include <backend/BufferDescriptor.h>
#include <utils/compiler.h>
#include <stdint.h>
#include <stddef.h>
namespace filament {
class FBufferObject;
+7 -2
View File
@@ -28,6 +28,11 @@
#include <math/vec4.h>
#include <math/mat4.h>
#include <math.h>
#include <stdint.h>
#include <stddef.h>
namespace utils {
class Entity;
} // namespace utils
@@ -184,7 +189,7 @@ public:
* @see Fov.
*/
static math::mat4 projection(Fov direction, double fovInDegrees,
double aspect, double near, double far = std::numeric_limits<double>::infinity());
double aspect, double near, double far = INFINITY);
/** Returns the projection matrix from the focal length.
*
@@ -194,7 +199,7 @@ public:
* @param far distance in world units from the camera to the far plane. \p far > \p near.
*/
static math::mat4 projection(double focalLengthInMillimeters,
double aspect, double near, double far = std::numeric_limits<double>::infinity());
double aspect, double near, double far = INFINITY);
/** Sets the projection matrix from a frustum defined by six planes.
+3
View File
@@ -24,6 +24,9 @@
#include <math/vec3.h>
#include <math/vec4.h>
#include <stdint.h>
#include <stddef.h>
namespace filament {
//! RGB color in linear space
+3
View File
@@ -26,6 +26,9 @@
#include <math/mathfwd.h>
#include <stdint.h>
#include <stddef.h>
namespace filament {
class Engine;
-1
View File
@@ -18,7 +18,6 @@
#define TNT_FILAMENT_COLOR_SPACE_H
#include <math/vec2.h>
#include <math/vec3.h>
namespace filament::color {
+1 -1
View File
@@ -25,7 +25,7 @@
#include <math/mathfwd.h>
#include <stdint.h>
#include <stddef.h>
namespace filament {
+5
View File
@@ -19,9 +19,14 @@
#include <filament/FilamentAPI.h>
#include <backend/DriverEnums.h>
#include <backend/Platform.h>
#include <utils/compiler.h>
#include <utils/Invocable.h>
#include <stdint.h>
#include <stddef.h>
namespace utils {
class Entity;
+2
View File
@@ -25,6 +25,8 @@
#include <utils/compiler.h>
#include <stdint.h>
namespace filament {
/**
+3
View File
@@ -23,9 +23,12 @@
#include <math/mat4.h>
#include <math/vec3.h>
#include <math/vec4.h>
#include <utils/unwindows.h> // Because we define NEAR and FAR in the Plane enum.
#include <stdint.h>
namespace filament {
class Box;
+1
View File
@@ -27,6 +27,7 @@
#include <utils/compiler.h>
#include <stdint.h>
#include <stddef.h>
namespace filament {
@@ -25,6 +25,8 @@
#include <math/mathfwd.h>
#include <stdint.h>
namespace filament {
class Engine;
+5 -2
View File
@@ -18,11 +18,14 @@
#define TNT_FILAMENT_INSTANCEBUFFER_H
#include <filament/FilamentAPI.h>
#include <filament/Engine.h>
#include <utils/compiler.h>
#include <math/mathfwd.h>
#include <stddef.h>
namespace filament {
/**
@@ -45,7 +48,7 @@ public:
* >= 1 and <= \c Engine::getMaxAutomaticInstances()
* @see Engine::getMaxAutomaticInstances
*/
Builder(size_t instanceCount) noexcept;
explicit Builder(size_t instanceCount) noexcept;
Builder(Builder const& rhs) noexcept;
Builder(Builder&& rhs) noexcept;
+3
View File
@@ -27,6 +27,9 @@
#include <math/mathfwd.h>
#include <math/quat.h>
#include <stdint.h>
#include <stddef.h>
namespace utils {
class Entity;
} // namespace utils
+5
View File
@@ -30,7 +30,12 @@
#include <math/mathfwd.h>
#include <type_traits>
#include <utility>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
namespace utils {
class CString;
@@ -28,6 +28,12 @@
#include <math/mathfwd.h>
#include <type_traits>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
namespace filament {
class Material;
@@ -21,8 +21,11 @@
#include <filament/Engine.h>
#include <utils/compiler.h>
#include <math/mathfwd.h>
#include <stddef.h>
namespace filament {
+4 -1
View File
@@ -19,10 +19,13 @@
#include <filament/Color.h>
#include <stdint.h>
#include <math/vec2.h>
#include <math/vec3.h>
#include <math.h>
#include <stdint.h>
namespace filament {
class Texture;
+3
View File
@@ -24,7 +24,10 @@
#include <backend/DriverEnums.h>
#include <backend/TargetBufferInfo.h>
#include <utils/compiler.h>
#include <stddef.h>
#include <stdint.h>
namespace filament {
@@ -29,9 +29,15 @@
#include <utils/FixedCapacityVector.h>
#include <math/mathfwd.h>
#include <math/vec3.h>
#include <math/vec4.h>
#include <type_traits>
#include <float.h>
#include <stddef.h>
#include <stdint.h>
namespace utils {
class Entity;
} // namespace utils
@@ -873,8 +879,8 @@ void RenderableManager::setMorphTargetBufferAt(Instance instance, uint8_t level,
template<typename VECTOR, typename INDEX, typename, typename>
Box RenderableManager::computeAABB(VECTOR const* vertices, INDEX const* indices, size_t count,
size_t stride) noexcept {
math::float3 bmin(std::numeric_limits<float>::max());
math::float3 bmax(std::numeric_limits<float>::lowest());
math::float3 bmin(FLT_MAX);
math::float3 bmax(-FLT_MAX);
for (size_t i = 0; i < count; ++i) {
VECTOR const* p = reinterpret_cast<VECTOR const*>(
(char const*)vertices + indices[i] * stride);
-3
View File
@@ -23,9 +23,6 @@
#include <utils/compiler.h>
#include <backend/PresentCallable.h>
#include <backend/DriverEnums.h>
#include <math/vec4.h>
#include <stdint.h>
+2
View File
@@ -24,6 +24,8 @@
#include <utils/compiler.h>
#include <utils/Invocable.h>
#include <stddef.h>
namespace utils {
class Entity;
} // namespace utils
+1 -1
View File
@@ -26,7 +26,7 @@
#include <math/mathfwd.h>
#include <stddef.h>
#include <stdint.h>
namespace filament {
+2 -1
View File
@@ -23,9 +23,10 @@
#include <utils/compiler.h>
#include <stdint.h>
#include <math/mathfwd.h>
#include <stdint.h>
namespace filament {
class FSkybox;
+2 -2
View File
@@ -20,12 +20,12 @@
#include <filament/FilamentAPI.h>
#include <backend/DriverEnums.h>
#include <backend/PixelBufferDescriptor.h>
#include <backend/CallbackHandler.h>
#include <utils/compiler.h>
#include <stdint.h>
namespace filament {
class FStream;
+2 -1
View File
@@ -21,11 +21,12 @@
#include <backend/CallbackHandler.h>
#include <backend/DriverEnums.h>
#include <backend/PresentCallable.h>
#include <utils/compiler.h>
#include <utils/Invocable.h>
#include <stdint.h>
namespace filament {
class Engine;
+4
View File
@@ -20,12 +20,16 @@
#define TNT_FILAMENT_TEXTURE_H
#include <filament/FilamentAPI.h>
#include <backend/DriverEnums.h>
#include <backend/PixelBufferDescriptor.h>
#include <utils/compiler.h>
#include <utility>
#include <stddef.h>
#include <stdint.h>
namespace filament {
@@ -25,6 +25,8 @@
#include <math.h>
#include <stdint.h>
namespace filament {
/**
+2
View File
@@ -21,6 +21,8 @@
#include <math/mathfwd.h>
#include <stdint.h>
namespace filament {
/**
@@ -26,6 +26,7 @@
#include <iterator>
#include <stddef.h>
namespace utils {
class Entity;
+3
View File
@@ -27,6 +27,9 @@
#include <utils/compiler.h>
#include <stddef.h>
#include <stdint.h>
namespace filament {
class FVertexBuffer;
+5 -3
View File
@@ -19,17 +19,19 @@
#ifndef TNT_FILAMENT_VIEW_H
#define TNT_FILAMENT_VIEW_H
#include <filament/Color.h>
#include <filament/FilamentAPI.h>
#include <filament/Options.h>
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
#include <utils/Entity.h>
#include <math/mathfwd.h>
#include <utility>
#include <stddef.h>
#include <stdint.h>
namespace filament {
namespace backend {
-3
View File
@@ -23,9 +23,6 @@
#include <utils/compiler.h>
#include <math/scalar.h>
#include <math/mathfwd.h>
#include <stddef.h>
#include <stdint.h>
+50 -2
View File
@@ -307,6 +307,7 @@ static const PostProcessManager::MaterialInfo sMaterialList[] = {
{ "fsr_rcas", MATERIAL(FSR_RCAS) },
{ "debugShadowCascades", MATERIAL(DEBUGSHADOWCASCADES) },
{ "resolveDepth", MATERIAL(RESOLVEDEPTH) },
{ "shadowmap", MATERIAL(SHADOWMAP) },
};
void PostProcessManager::init() noexcept {
@@ -2809,8 +2810,8 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::rcas(
auto& ppFsrRcas = fg.addPass<QuadBlitData>("FidelityFX FSR1 Rcas",
[&](FrameGraph::Builder& builder, auto& data) {
data.input = builder.sample(input);
data.input = builder.createTexture("FFX FSR1 Rcas output", outDesc);
data.input = builder.declareRenderPass(data.input);
data.output = builder.createTexture("FFX FSR1 Rcas output", outDesc);
data.output = builder.declareRenderPass(data.output);
},
[=](FrameGraphResources const& resources,
auto const& data, DriverApi& driver) {
@@ -3273,4 +3274,51 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::debugShadowCascades(FrameGra
return debugShadowCascadePass->output;
}
FrameGraphId<FrameGraphTexture> PostProcessManager::debugDisplayShadowTexture(
FrameGraph& fg,
FrameGraphId<FrameGraphTexture> input,
FrameGraphId<FrameGraphTexture> shadowmap, float scale,
uint8_t layer, uint8_t level, uint8_t channel, float power) noexcept {
if (shadowmap) {
struct ShadowMapData {
FrameGraphId<FrameGraphTexture> color;
FrameGraphId<FrameGraphTexture> depth;
};
auto const& desc = fg.getDescriptor(input);
float const ratio = float(desc.height) / float(desc.width);
float const screenScale = float(fg.getDescriptor(shadowmap).height) / float(desc.height);
float2 const s = { screenScale * scale * ratio, screenScale * scale };
auto& shadomapDebugPass = fg.addPass<ShadowMapData>("shadowmap debug pass",
[&](FrameGraph::Builder& builder, auto& data) {
data.color = builder.read(input,
FrameGraphTexture::Usage::COLOR_ATTACHMENT);
data.color = builder.write(data.color,
FrameGraphTexture::Usage::COLOR_ATTACHMENT);
data.depth = builder.sample(shadowmap);
builder.declareRenderPass("color target", {
.attachments = { .color = { data.color }}
});
},
[=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) {
auto out = resources.getRenderPassInfo();
auto in = resources.getTexture(data.depth);
auto const& material = getPostProcessMaterial("shadowmap");
FMaterialInstance* const mi = material.getMaterialInstance(mEngine);
mi->setParameter("shadowmap", in, {
.filterMin = SamplerMinFilter::NEAREST_MIPMAP_NEAREST });
mi->setParameter("scale", s);
mi->setParameter("layer", (uint32_t)layer);
mi->setParameter("level", (uint32_t)level);
mi->setParameter("channel", (uint32_t)channel);
mi->setParameter("power", power);
commitAndRender(out, material, driver);
});
input = shadomapDebugPass->color;
}
return input;
}
} // namespace filament
+5
View File
@@ -282,6 +282,11 @@ public:
FrameGraphId<FrameGraphTexture> input,
FrameGraphId<FrameGraphTexture> depth) noexcept;
FrameGraphId<FrameGraphTexture> debugDisplayShadowTexture(FrameGraph& fg,
FrameGraphId<FrameGraphTexture> input,
FrameGraphId<FrameGraphTexture> shadowmap, float scale,
uint8_t layer, uint8_t level, uint8_t channel, float power) noexcept;
backend::Handle<backend::HwTexture> getOneTexture() const;
backend::Handle<backend::HwTexture> getZeroTexture() const;
backend::Handle<backend::HwTexture> getOneTextureArray() const;
+6
View File
@@ -294,6 +294,8 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
// Shadow Passes
// -------------------------------------------------------------------------------------------
fg.getBlackboard()["shadowmap"] = prepareShadowPass->shadows;
struct ShadowPassData {
FrameGraphId<FrameGraphTexture> tempBlurSrc{}; // temporary shadowmap when blurring
FrameGraphId<FrameGraphTexture> output;
@@ -943,6 +945,10 @@ void ShadowMapManager::calculateTextureRequirements(FEngine& engine, FView& view
mipLevels = std::max(1, FTexture::maxLevelCount(maxDimension) - lowMipmapLevel);
}
// publish the debugging data
engine.debug.shadowmap.display_shadow_texture_layer_count = layersNeeded;
engine.debug.shadowmap.display_shadow_texture_level_count = mipLevels;
mTextureAtlasRequirements = {
(uint16_t)maxDimension,
layersNeeded,
+8
View File
@@ -548,12 +548,20 @@ public:
struct {
struct {
bool debug_directional_shadowmap = false;
bool display_shadow_texture = false;
bool far_uses_shadowcasters = true;
bool focus_shadowcasters = true;
bool visualize_cascades = false;
bool tightly_bound_scene = true;
float dzn = -1.0f;
float dzf = 1.0f;
float display_shadow_texture_scale = 0.25f;
int display_shadow_texture_layer = 0;
int display_shadow_texture_level = 0;
int display_shadow_texture_channel = 0;
int display_shadow_texture_layer_count = 0;
int display_shadow_texture_level_count = 0;
float display_shadow_texture_power = 1;
} shadowmap;
struct {
bool camera_at_origin = true;
+26
View File
@@ -70,6 +70,22 @@ FRenderer::FRenderer(FEngine& engine) :
&engine.debug.renderer.doFrameCapture);
debugRegistry.registerProperty("d.renderer.disable_buffer_padding",
&engine.debug.renderer.disable_buffer_padding);
debugRegistry.registerProperty("d.shadowmap.display_shadow_texture",
&engine.debug.shadowmap.display_shadow_texture);
debugRegistry.registerProperty("d.shadowmap.display_shadow_texture_scale",
&engine.debug.shadowmap.display_shadow_texture_scale);
debugRegistry.registerProperty("d.shadowmap.display_shadow_texture_layer",
&engine.debug.shadowmap.display_shadow_texture_layer);
debugRegistry.registerProperty("d.shadowmap.display_shadow_texture_level",
&engine.debug.shadowmap.display_shadow_texture_level);
debugRegistry.registerProperty("d.shadowmap.display_shadow_texture_channel",
&engine.debug.shadowmap.display_shadow_texture_channel);
debugRegistry.registerProperty("d.shadowmap.display_shadow_texture_layer_count",
&engine.debug.shadowmap.display_shadow_texture_layer_count);
debugRegistry.registerProperty("d.shadowmap.display_shadow_texture_level_count",
&engine.debug.shadowmap.display_shadow_texture_level_count);
debugRegistry.registerProperty("d.shadowmap.display_shadow_texture_power",
&engine.debug.shadowmap.display_shadow_texture_power);
DriverApi& driver = engine.getDriverApi();
@@ -1133,6 +1149,16 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
"SwapChain::CONFIG_HAS_STENCIL_BUFFER flag set.");
}
if (UTILS_UNLIKELY(engine.debug.shadowmap.display_shadow_texture)) {
auto shadowmap = blackboard.get<FrameGraphTexture>("shadowmap");
input = ppm.debugDisplayShadowTexture(fg, input, shadowmap,
engine.debug.shadowmap.display_shadow_texture_scale,
engine.debug.shadowmap.display_shadow_texture_layer,
engine.debug.shadowmap.display_shadow_texture_level,
engine.debug.shadowmap.display_shadow_texture_channel,
engine.debug.shadowmap.display_shadow_texture_power);
}
// auto debug = structure
// fg.forwardResource(fgViewRenderTarget, debug ? debug : input);
+59
View File
@@ -0,0 +1,59 @@
material {
name : shadowmap,
parameters : [
{
type : sampler2dArray,
name : shadowmap,
precision : high
},
{
type : float,
name : power,
precision : high
},
{
type : float2,
name : scale,
},
{
type : int,
name : layer
},
{
type : int,
name : level
},
{
type : int,
name : channel
}
],
variables : [
vertex
],
vertexDomain : device,
depthWrite : false,
depthCulling : false,
domain: postprocess
}
vertex {
void postProcessVertex(inout PostProcessVertexInputs postProcess) {
postProcess.vertex.xy = postProcess.normalizedUV;
postProcess.position.xy = 1.0 + (postProcess.position.xy - 1.0) * materialParams.scale;
}
}
fragment {
void dummy(){}
void postProcess(inout PostProcessInputs postProcess) {
highp vec2 uv = uvToRenderTargetUV(variable_vertex.xy);
highp vec3 p = vec3(uv, float(materialParams.layer));
float m = float(materialParams.level);
highp float c = textureLod(materialParams_shadowmap, p, m)[materialParams.channel];
c = pow(abs(c), materialParams.power);
postProcess.color.rgb = vec3(c);
postProcess.color.a = 1.0;
}
}
+2 -2
View File
@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
spec.version = "1.50.1"
spec.version = "1.50.0"
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
spec.homepage = "https://google.github.io/filament"
spec.authors = "Google LLC."
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
spec.platform = :ios, "11.0"
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.50.1/filament-v1.50.1-ios.tgz" }
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.50.0/filament-v1.50.0-ios.tgz" }
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
spec.pod_target_xcconfig = {
+108
View File
@@ -0,0 +1,108 @@
cmake_minimum_required(VERSION 3.19)
project(astrict)
set(TARGET astrict)
set(PUBLIC_HDR_DIR include)
# ==================================================================================================
# Sources and headers
# ==================================================================================================
set(HDRS
include/astrict/CommonTypes.h
include/astrict/DebugCommon.h
include/astrict/DebugGlsl.h
include/astrict/FromGlsl.h
include/astrict/GlslTypes.h
include/astrict/ToGlsl.h)
set(PRIVATE_HDRS)
set(SRCS
src/DebugCommon.cpp
src/DebugGlsl.cpp
src/FromGlsl.cpp
src/ToGlsl.cpp)
# ==================================================================================================
# Include and target definitions
# ==================================================================================================
include_directories(${PUBLIC_HDR_DIR})
include_directories(${CMAKE_BINARY_DIR})
# astrict
add_library(${TARGET} STATIC ${HDRS} ${PRIVATE_HDRS} ${SRCS})
target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
set_target_properties(${TARGET} PROPERTIES FOLDER Libs)
target_link_libraries(${TARGET} backend_headers math utils)
# We are being naughty and accessing private headers here
# For spirv-tools, we're just following glslang's example
target_include_directories(${TARGET} PRIVATE ${spirv-tools_SOURCE_DIR}/include)
# glslang libraries have circular dependencies. To make sure the proper object are part of the link
# we need to force archive re-scan on new symbol dependencies via start/end-group.
# Read more about this here https://eli.thegreenplace.net/2013/07/09/library-order-in-static-linking
if (APPLE OR MSVC)
target_link_libraries(${TARGET} glslang SPIRV SPIRV-Tools-opt spirv-cross-glsl)
else()
target_link_libraries(${TARGET}
-Wl,--start-group glslang SPIRV SPIRV-Tools-opt spirv-cross-glsl -Wl,--end-group)
endif()
# ==================================================================================================
# Compiler flags
# ==================================================================================================
# this must match options enabled in glslang's CMakeLists.txt
target_compile_options(${TARGET} PRIVATE -DAMD_EXTENSIONS -DNV_EXTENSIONS )
if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W0 /Zc:__cplusplus")
endif()
if (FILAMENT_ENABLE_MATDBG)
add_definitions(-DFILAMENT_ENABLE_MATDBG)
endif()
# ==================================================================================================
# Installation
# ==================================================================================================
# Astrict has dependencies on a bunch of SPIRV-related libraries. To make things simpler, we bundle
# them together into a single shared library and copy this into the installation folder. This
# requires us to explicitly list the dependencies below, as CMake doesn't have a way to recursively
# query dependencies.
set(ASTRICT_DEPS
OGLCompiler
OSDependent
SPIRV
SPIRV-Tools
SPIRV-Tools-opt
astrict
glslang
spirv-cross-core
spirv-cross-glsl
spirv-cross-msl
)
set(ASTRICT_COMBINED_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libastrict_combined.a")
combine_static_libs(astrict "${ASTRICT_COMBINED_OUTPUT}" "${ASTRICT_DEPS}")
set(ASTRICT_LIB_NAME ${CMAKE_STATIC_LIBRARY_PREFIX}astrict${CMAKE_STATIC_LIBRARY_SUFFIX})
install(FILES "${ASTRICT_COMBINED_OUTPUT}" DESTINATION lib/${DIST_DIR} RENAME ${ASTRICT_LIB_NAME})
install(DIRECTORY ${PUBLIC_HDR_DIR}/astrict DESTINATION include)
# ==================================================================================================
# Tests
# ==================================================================================================
project(test_astrict)
set(TARGET test_astrict)
set(SRCS
tests/test_FromGlsl.cpp)
add_executable(${TARGET} ${SRCS})
target_include_directories(${TARGET} PRIVATE src)
target_link_libraries(${TARGET} astrict gtest)
set_target_properties(${TARGET} PROPERTIES FOLDER Tests)
@@ -0,0 +1,86 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_ASTRICT_ASTRICT_BUILDER_H
#define TNT_ASTRICT_ASTRICT_BUILDER_H
#include <set>
#include <unordered_map>
#include <astrict/CommonTypes.h>
namespace astrict {
using StringId = Newtype<int, struct StringIdTag>;
using ExpressionId = Newtype<int, struct ExpressionIdTag>;
using GlobalVariableId = Newtype<int, struct GlobalVariableIdTag>;
using StructId = Newtype<int, struct StructIdTag>;
using FunctionId = Newtype<int, struct FunctionIdTag>;
using LocalVariableId = Newtype<int, struct LocalVariableIdTag>;
template<typename Id, typename Value>
class IdStore {
public:
// Inserts if non-existent.
Id insert(Value value, bool* outWasExtant = nullptr) {
auto it = mMap.find(value);
if (it == mMap.end()) {
Id id(mMap.size() + 1);
mMap[value] = id;
if (outWasExtant) {
*outWasExtant = false;
}
return id;
}
if (outWasExtant) {
*outWasExtant = true;
}
return it->second;
}
std::vector<Value> getFinal() {
std::vector<Value> r(mMap.size());
for (const auto& pair : mMap) {
r[pair.second] = pair.first;
}
return r;
}
private:
std::unordered_map<Value, Id> mMap;
};
using ByteVector = std::vector<uint8_t>;
class AstrictBuilder {
public:
std::vector<ByteVector> build();
private:
IdStore<StringId, std::string> mStrings;
IdStore<ExpressionId, ByteVector> mExpressions;
IdStore<StructId, ByteVector> mStructs;
IdStore<GlobalVariableId, ByteVector> mGlobalSymbols;
IdStore<FunctionId, ByteVector> mFunctions;
IdStore<FunctionId, ByteVector> mFunctionBodies;
std::unordered_map<StructId, std::string> mStructNames;
std::unordered_map<GlobalVariableId, std::string> mGlobalVariableNames;
};
} // namespace astrict
#endif // TNT_ASTRICT_ASTRICT_BUILDER_H
+473
View File
@@ -0,0 +1,473 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_ASTRICT_COMMONTYPES_H
#define TNT_ASTRICT_COMMONTYPES_H
#include <variant>
#include <vector>
namespace astrict {
template<typename T, typename Tag>
class Newtype {
public:
Newtype() : mValue() {}
Newtype(const Newtype<T, Tag> &other) : mValue(other.mValue) {}
Newtype(Newtype<T, Tag> &&other) : mValue(other.mValue) {}
explicit Newtype(T& value) : mValue(value) {}
explicit Newtype(T&& value) : mValue(value) {}
Newtype& operator=(const Newtype<T, Tag>& other) {
mValue = other.mValue;
return *this;
}
Newtype& operator=(Newtype<T, Tag>&& other) {
mValue = other.mValue;
return *this;
}
const T& operator*() const {
return mValue;
}
bool operator==(const Newtype<T, Tag>& o) const {
return mValue == o.mValue;
}
bool operator<(const Newtype<T, Tag>& o) const {
return mValue < o.mValue;
}
private:
T mValue;
};
template<class>
inline constexpr bool always_false_v = false;
} // namespace astrict
namespace std {
template<typename Tag>
struct hash<astrict::Newtype<int, Tag>> {
std::size_t operator()(const astrict::Newtype<int, Tag>& o) const {
return *o;
}
};
template<typename Tag>
struct hash<astrict::Newtype<uint16_t, Tag>> {
std::size_t operator()(const astrict::Newtype<uint16_t, Tag>& o) const {
return *o;
}
};
} // namespace std
namespace astrict {
enum class BranchOperator : uint8_t {
Discard, // Fragment only
TerminateInvocation, // Fragment only
Demote, // Fragment only
TerminateRayEXT, // Any-hit only
IgnoreIntersectionEXT, // Any-hit only
Return,
Break,
Continue,
Case,
Default,
};
// Represents an operation whose syntax differs from a function call. For example, addition,
// equality.
enum class ExpressionOperator : uint8_t {
// Unary
Negative,
LogicalNot,
BitwiseNot,
PostIncrement,
PostDecrement,
PreIncrement,
PreDecrement,
ArrayLength,
// Binary
Add,
Sub,
Mul,
Div,
Mod,
RightShift,
LeftShift,
And,
InclusiveOr,
ExclusiveOr,
Equal,
NotEqual,
LessThan,
GreaterThan,
LessThanEqual,
GreaterThanEqual,
LogicalOr,
LogicalXor,
LogicalAnd,
Index,
Assign,
AddAssign,
SubAssign,
MulAssign,
DivAssign,
ModAssign,
AndAssign,
InclusiveOrAssign,
ExclusiveOrAssign,
LeftShiftAssign,
RightShiftAssign,
// Ternary
Ternary,
// Variadic
Comma,
};
using VariableOrExpressionId = std::variant<GlobalVariableId, LocalVariableId, ExpressionId>;
struct StructMember {
StringId qualifier;
StringId type;
bool operator==(const StructMember& o) const {
return qualifier == o.qualifier
&& type == o.type;
}
};
struct Struct {
StringId qualifier;
std::vector<StructMember> members;
std::vector<StringId> memberNames;
bool operator==(const Struct& o) const {
return qualifier == o.qualifier
&& members == o.members
&& memberNames == o.memberNames;
}
};
struct Type {
std::variant<StringId, StructId> name;
std::optional<StringId> qualifiers;
std::vector<std::size_t> arraySizes;
bool operator==(const Type& o) const {
return name == o.name
&& qualifiers == o.qualifiers
&& arraySizes == o.arraySizes;
}
};
struct Variable {
StringId qualifier;
StringId type;
std::optional<StringId> name;
bool operator==(const Variable& o) const {
return qualifier == o.qualifier
&& type == o.type
&& name == o.name;
}
};
struct ExpressionOperandExpression {
std::variant<ExpressionOperator, FunctionId, StructId> op;
std::vector<VariableOrExpressionId> args;
bool operator==(const ExpressionOperandExpression& o) const {
return op == o.op
&& args == o.args;
}
};
struct VectorSwizzleExpression {
VariableOrExpressionId operand;
uint16_t swizzle;
bool operator==(const VectorSwizzleExpression& o) const {
return operand == o.operand
&& swizzle == o.swizzle;
}
};
struct IndexStructExpression {
VariableOrExpressionId operand;
StructId strukt;
uint16_t index;
bool operator==(const IndexStructExpression& o) const {
return operand == o.operand
&& strukt == o.strukt
&& index == o.index;
}
};
struct LiteralExpression {
std::variant<
bool,
int,
double,
unsigned int> value;
bool operator==(const LiteralExpression& o) const {
return value == o.value;
}
};
using Expression = std::variant<
ExpressionOperandExpression,
VectorSwizzleExpression,
IndexStructExpression,
LiteralExpression>;
struct Function {
FunctionId name;
TypeId returnType;
std::vector<LocalVariableId> parameters;
StatementBlockId body;
std::unordered_map<LocalVariableId, Variable> localVariables;
bool operator==(const Function& o) const {
return name == o.name
&& returnType == o.returnType
&& parameters == o.parameters
&& body == o.body
&& localVariables == o.localVariables;
}
};
struct IfStatement {
VariableOrExpressionId condition;
StatementBlockId thenBlock;
std::optional<StatementBlockId> elseBlock;
bool operator==(const IfStatement& o) const {
return condition == o.condition
&& thenBlock == o.thenBlock
&& elseBlock == o.elseBlock;
}
};
struct SwitchStatement {
VariableOrExpressionId condition;
StatementBlockId body;
bool operator==(const SwitchStatement& o) const {
return condition == o.condition
&& body == o.body;
}
};
struct BranchStatement {
BranchOperator op;
std::optional<VariableOrExpressionId> operand;
bool operator==(const BranchStatement& o) const {
return op == o.op
&& operand == o.operand;
}
};
struct LoopStatement {
VariableOrExpressionId condition;
std::optional<ExpressionId> terminal;
bool testFirst;
StatementBlockId body;
bool operator==(const LoopStatement& o) const {
return condition == o.condition
&& terminal == o.terminal
&& testFirst == o.testFirst
&& body == o.body;
}
};
using Statement = std::variant<
ExpressionId,
IfStatement,
SwitchStatement,
BranchStatement,
LoopStatement>;
template <typename T, typename... Rest>
void hashCombine(std::size_t& seed, const T& v, const Rest&... rest) {
seed ^= std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
(hashCombine(seed, rest), ...);
}
} // namespace astrict
namespace std {
template<>
struct hash<astrict::StructMember> {
std::size_t operator()(const astrict::StructMember& o) const {
std::size_t result = 0;
astrict::hashCombine(result, o.name, o.type);
return result;
}
};
template<>
struct hash<astrict::Struct> {
std::size_t operator()(const astrict::Struct& o) const {
std::size_t result = 0;
astrict::hashCombine(result, o.name, o.members.size());
for (const auto& member : o.members) {
astrict::hashCombine(result, member);
}
return result;
}
};
template<>
struct hash<astrict::Type> {
std::size_t operator()(const astrict::Type& o) const {
std::size_t result = 0;
astrict::hashCombine(result, o.name, o.qualifiers, o.arraySizes.size());
for (const auto& size : o.arraySizes) {
astrict::hashCombine(result, size);
}
return result;
}
};
template<>
struct hash<astrict::Variable> {
std::size_t operator()(const astrict::Variable& o) const {
std::size_t result = 0;
astrict::hashCombine(result, o.name, o.type);
return result;
}
};
template<>
struct hash<astrict::ExpressionOperandExpression> {
std::size_t operator()(const astrict::ExpressionOperandExpression& o) const {
std::size_t result = 0;
astrict::hashCombine(result, o.op, o.args.size());
for (const auto& arg : o.args) {
astrict::hashCombine(result, arg);
}
return result;
}
};
template<>
struct hash<astrict::IndexStructExpression> {
std::size_t operator()(const astrict::IndexStructExpression& o) const {
std::size_t result = 0;
astrict::hashCombine(result, o.operand, o.strukt, o.index);
return result;
}
};
template<>
struct hash<astrict::VectorSwizzleExpression> {
std::size_t operator()(const astrict::VectorSwizzleExpression& o) const {
std::size_t result = 0;
astrict::hashCombine(result, o.operand, o.swizzle);
return result;
}
};
template<>
struct hash<astrict::LiteralExpression> {
std::size_t operator()(const astrict::LiteralExpression& o) const {
std::size_t result = 0;
astrict::hashCombine(result, o.value);
return result;
}
};
template<>
struct hash<astrict::Function> {
std::size_t operator()(const astrict::Function& o) const {
std::size_t result = 0;
astrict::hashCombine(result, o.name, o.returnType, o.body,
o.parameters.size(), o.localVariables.size());
for (const auto& argument : o.parameters) {
astrict::hashCombine(result, argument);
}
for (const auto& symbol : o.localVariables) {
astrict::hashCombine(result, symbol.first, symbol.second);
}
return result;
}
};
template<>
struct hash<astrict::IfStatement> {
std::size_t operator()(const astrict::IfStatement& o) const {
std::size_t result = 0;
astrict::hashCombine(result, o.condition, o.thenBlock, o.elseBlock);
return result;
}
};
template<>
struct hash<astrict::SwitchStatement> {
std::size_t operator()(const astrict::SwitchStatement& o) const {
std::size_t result = 0;
astrict::hashCombine(result, o.condition, o.body);
return result;
}
};
template<>
struct hash<astrict::BranchStatement> {
std::size_t operator()(const astrict::BranchStatement& o) const {
std::size_t result = 0;
astrict::hashCombine(result, o.op, o.operand);
return result;
}
};
template<>
struct hash<astrict::LoopStatement> {
std::size_t operator()(const astrict::LoopStatement& o) const {
std::size_t result = 0;
astrict::hashCombine(result, o.condition, o.terminal, o.testFirst, o.body);
return result;
}
};
template<>
struct hash<std::vector<astrict::Statement>> {
std::size_t operator()(const std::vector<astrict::Statement>& o) const {
std::size_t result = o.size();
for (const auto& statement : o) {
astrict::hashCombine(result, statement);
}
return result;
}
};
} // namespace std
#endif // TNT_ASTRICT_COMMONTYPES_H
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_ASTRICT_DEBUGCOMMON_H
#define TNT_ASTRICT_DEBUGCOMMON_H
#include <astrict/CommonTypes.h>
namespace astrict {
const char* rValueOperatorToString(ExpressionOperator op);
} // namespace astrict
#endif // TNT_ASTRICT_DEBUGCOMMON_H
+31
View File
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_ASTRICT_DEBUGGLSL_H
#define TNT_ASTRICT_DEBUGGLSL_H
#include "glslang/Include/intermediate.h"
namespace astrict {
const char* glslangOperatorToString(glslang::TOperator op);
std::string glslangNodeToString(const TIntermNode* node);
std::string glslangLocToString(const glslang::TSourceLoc& loc);
std::string glslangNodeToStringWithLoc(const TIntermNode* node);
} // namespace astrict
#endif // TNT_ASTRICT_DEBUGGLSL_H
+30
View File
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_ASTRICT_FROMGLSL_H
#define TNT_ASTRICT_FROMGLSL_H
#include <astrict/GlslTypes.h>
#include "glslang/Include/intermediate.h"
namespace astrict {
PackFromGlsl fromGlsl(const glslang::TIntermediate& intermediate);
} // namespace astrict
#endif // TNT_ASTRICT_FROMGLSL_H
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_ASTRICT_GLSLTYPES_H
#define TNT_ASTRICT_GLSLTYPES_H
#include <astrict/CommonTypes.h>
#include <set>
#include <unordered_map>
#include <vector>
namespace astrict {
struct PackFromGlsl {
int version;
std::unordered_map<StringId, std::string> strings;
std::unordered_map<TypeId, Type> types;
std::unordered_map<StructId, Struct> structs;
std::unordered_map<GlobalVariableId, Variable> globalVariables;
std::unordered_map<ExpressionId, Expression> expressions;
std::unordered_map<FunctionId, std::string> functionNames;
std::unordered_map<StatementBlockId, std::vector<Statement>> statementBlocks;
std::unordered_map<FunctionId, Function> functions;
// The below serve as the roots for conversion to glsl.
std::vector<StructId> structsInOrder;
std::set<FunctionId> functionPrototypes;
std::vector<std::pair<GlobalVariableId, VariableOrExpressionId>> globalSymbolsInOrder;
std::vector<FunctionId> functionsInOrder;
};
};
#endif // TNT_ASTRICT_GLSLTYPES_H
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_ASTRICT_TOGLSL_H
#define TNT_ASTRICT_TOGLSL_H
#include <astrict/GlslTypes.h>
#include <sstream>
namespace astrict {
void toGlsl(const PackFromGlsl& pack, std::ostringstream& out);
};
#endif // TNT_ASTRICT_TOGLSL_H
+36
View File
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <astrict/AstrictBuilder.h>
#include <astrict/CommonTypes.h>
#include <astrict/DebugGlsl.h>
#include <utils/Log.h>
#include <utils/Panic.h>
#include <optional>
#include <set>
#include "ConstantUnion.h"
#include "Types.h"
#include "glslang/MachineIndependent/localintermediate.h"
#include "intermediate.h"
#include "utils/ostream.h"
namespace astrict {
} // namespace astrict
+67
View File
@@ -0,0 +1,67 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <astrict/DebugCommon.h>
namespace astrict {
const char* rValueOperatorToString(ExpressionOperator op) {
switch(op) {
case ExpressionOperator::Negative: return "Negative";
case ExpressionOperator::LogicalNot: return "LogicalNot";
case ExpressionOperator::BitwiseNot: return "BitwiseNot";
case ExpressionOperator::PostIncrement: return "PostIncrement";
case ExpressionOperator::PostDecrement: return "PostDecrement";
case ExpressionOperator::PreIncrement: return "PreIncrement";
case ExpressionOperator::PreDecrement: return "PreDecrement";
case ExpressionOperator::ArrayLength: return "ArrayLength";
case ExpressionOperator::Add: return "Add";
case ExpressionOperator::Sub: return "Sub";
case ExpressionOperator::Mul: return "Mul";
case ExpressionOperator::Div: return "Div";
case ExpressionOperator::Mod: return "Mod";
case ExpressionOperator::RightShift: return "RightShift";
case ExpressionOperator::LeftShift: return "LeftShift";
case ExpressionOperator::And: return "And";
case ExpressionOperator::InclusiveOr: return "InclusiveOr";
case ExpressionOperator::ExclusiveOr: return "ExclusiveOr";
case ExpressionOperator::Equal: return "Equal";
case ExpressionOperator::NotEqual: return "NotEqual";
case ExpressionOperator::LessThan: return "LessThan";
case ExpressionOperator::GreaterThan: return "GreaterThan";
case ExpressionOperator::LessThanEqual: return "LessThanEqual";
case ExpressionOperator::GreaterThanEqual: return "GreaterThanEqual";
case ExpressionOperator::LogicalOr: return "LogicalOr";
case ExpressionOperator::LogicalXor: return "LogicalXor";
case ExpressionOperator::LogicalAnd: return "LogicalAnd";
case ExpressionOperator::Index: return "Index";
case ExpressionOperator::Assign: return "Assign";
case ExpressionOperator::AddAssign: return "AddAssign";
case ExpressionOperator::SubAssign: return "SubAssign";
case ExpressionOperator::MulAssign: return "MulAssign";
case ExpressionOperator::DivAssign: return "DivAssign";
case ExpressionOperator::ModAssign: return "ModAssign";
case ExpressionOperator::AndAssign: return "AndAssign";
case ExpressionOperator::InclusiveOrAssign: return "InclusiveOrAssign";
case ExpressionOperator::ExclusiveOrAssign: return "ExclusiveOrAssign";
case ExpressionOperator::LeftShiftAssign: return "LeftShiftAssign";
case ExpressionOperator::RightShiftAssign: return "RightShiftAssign";
case ExpressionOperator::Ternary: return "Ternary";
case ExpressionOperator::Comma: return "Comma";
}
}
} // namespace astrict
+925
View File
@@ -0,0 +1,925 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <astrict/DebugGlsl.h>
namespace astrict {
const char* glslangOperatorToString(glslang::TOperator op) {
using namespace glslang;
switch (op) {
case EOpNull: return "EOpNull";
case EOpSequence: return "EOpSequence";
case EOpScope: return "EOpScope";
case EOpLinkerObjects: return "EOpLinkerObjects";
case EOpFunctionCall: return "EOpFunctionCall";
case EOpFunction: return "EOpFunction";
case EOpParameters: return "EOpParameters";
case EOpSpirvInst: return "EOpSpirvInst";
case EOpNegative: return "EOpNegative";
case EOpLogicalNot: return "EOpLogicalNot";
case EOpVectorLogicalNot: return "EOpVectorLogicalNot";
case EOpBitwiseNot: return "EOpBitwiseNot";
case EOpPostIncrement: return "EOpPostIncrement";
case EOpPostDecrement: return "EOpPostDecrement";
case EOpPreIncrement: return "EOpPreIncrement";
case EOpPreDecrement: return "EOpPreDecrement";
case EOpCopyObject: return "EOpCopyObject";
case EOpDeclare: return "EOpDeclare";
case EOpConvInt8ToBool: return "EOpConvInt8ToBool";
case EOpConvUint8ToBool: return "EOpConvUint8ToBool";
case EOpConvInt16ToBool: return "EOpConvInt16ToBool";
case EOpConvUint16ToBool: return "EOpConvUint16ToBool";
case EOpConvIntToBool: return "EOpConvIntToBool";
case EOpConvUintToBool: return "EOpConvUintToBool";
case EOpConvInt64ToBool: return "EOpConvInt64ToBool";
case EOpConvUint64ToBool: return "EOpConvUint64ToBool";
case EOpConvFloat16ToBool: return "EOpConvFloat16ToBool";
case EOpConvFloatToBool: return "EOpConvFloatToBool";
case EOpConvDoubleToBool: return "EOpConvDoubleToBool";
case EOpConvBoolToInt8: return "EOpConvBoolToInt8";
case EOpConvBoolToUint8: return "EOpConvBoolToUint8";
case EOpConvBoolToInt16: return "EOpConvBoolToInt16";
case EOpConvBoolToUint16: return "EOpConvBoolToUint16";
case EOpConvBoolToInt: return "EOpConvBoolToInt";
case EOpConvBoolToUint: return "EOpConvBoolToUint";
case EOpConvBoolToInt64: return "EOpConvBoolToInt64";
case EOpConvBoolToUint64: return "EOpConvBoolToUint64";
case EOpConvBoolToFloat16: return "EOpConvBoolToFloat16";
case EOpConvBoolToFloat: return "EOpConvBoolToFloat";
case EOpConvBoolToDouble: return "EOpConvBoolToDouble";
case EOpConvInt8ToInt16: return "EOpConvInt8ToInt16";
case EOpConvInt8ToInt: return "EOpConvInt8ToInt";
case EOpConvInt8ToInt64: return "EOpConvInt8ToInt64";
case EOpConvInt8ToUint8: return "EOpConvInt8ToUint8";
case EOpConvInt8ToUint16: return "EOpConvInt8ToUint16";
case EOpConvInt8ToUint: return "EOpConvInt8ToUint";
case EOpConvInt8ToUint64: return "EOpConvInt8ToUint64";
case EOpConvUint8ToInt8: return "EOpConvUint8ToInt8";
case EOpConvUint8ToInt16: return "EOpConvUint8ToInt16";
case EOpConvUint8ToInt: return "EOpConvUint8ToInt";
case EOpConvUint8ToInt64: return "EOpConvUint8ToInt64";
case EOpConvUint8ToUint16: return "EOpConvUint8ToUint16";
case EOpConvUint8ToUint: return "EOpConvUint8ToUint";
case EOpConvUint8ToUint64: return "EOpConvUint8ToUint64";
case EOpConvInt8ToFloat16: return "EOpConvInt8ToFloat16";
case EOpConvInt8ToFloat: return "EOpConvInt8ToFloat";
case EOpConvInt8ToDouble: return "EOpConvInt8ToDouble";
case EOpConvUint8ToFloat16: return "EOpConvUint8ToFloat16";
case EOpConvUint8ToFloat: return "EOpConvUint8ToFloat";
case EOpConvUint8ToDouble: return "EOpConvUint8ToDouble";
case EOpConvInt16ToInt8: return "EOpConvInt16ToInt8";
case EOpConvInt16ToInt: return "EOpConvInt16ToInt";
case EOpConvInt16ToInt64: return "EOpConvInt16ToInt64";
case EOpConvInt16ToUint8: return "EOpConvInt16ToUint8";
case EOpConvInt16ToUint16: return "EOpConvInt16ToUint16";
case EOpConvInt16ToUint: return "EOpConvInt16ToUint";
case EOpConvInt16ToUint64: return "EOpConvInt16ToUint64";
case EOpConvUint16ToInt8: return "EOpConvUint16ToInt8";
case EOpConvUint16ToInt16: return "EOpConvUint16ToInt16";
case EOpConvUint16ToInt: return "EOpConvUint16ToInt";
case EOpConvUint16ToInt64: return "EOpConvUint16ToInt64";
case EOpConvUint16ToUint8: return "EOpConvUint16ToUint8";
case EOpConvUint16ToUint: return "EOpConvUint16ToUint";
case EOpConvUint16ToUint64: return "EOpConvUint16ToUint64";
case EOpConvInt16ToFloat16: return "EOpConvInt16ToFloat16";
case EOpConvInt16ToFloat: return "EOpConvInt16ToFloat";
case EOpConvInt16ToDouble: return "EOpConvInt16ToDouble";
case EOpConvUint16ToFloat16: return "EOpConvUint16ToFloat16";
case EOpConvUint16ToFloat: return "EOpConvUint16ToFloat";
case EOpConvUint16ToDouble: return "EOpConvUint16ToDouble";
case EOpConvIntToInt8: return "EOpConvIntToInt8";
case EOpConvIntToInt16: return "EOpConvIntToInt16";
case EOpConvIntToInt64: return "EOpConvIntToInt64";
case EOpConvIntToUint8: return "EOpConvIntToUint8";
case EOpConvIntToUint16: return "EOpConvIntToUint16";
case EOpConvIntToUint: return "EOpConvIntToUint";
case EOpConvIntToUint64: return "EOpConvIntToUint64";
case EOpConvUintToInt8: return "EOpConvUintToInt8";
case EOpConvUintToInt16: return "EOpConvUintToInt16";
case EOpConvUintToInt: return "EOpConvUintToInt";
case EOpConvUintToInt64: return "EOpConvUintToInt64";
case EOpConvUintToUint8: return "EOpConvUintToUint8";
case EOpConvUintToUint16: return "EOpConvUintToUint16";
case EOpConvUintToUint64: return "EOpConvUintToUint64";
case EOpConvIntToFloat16: return "EOpConvIntToFloat16";
case EOpConvIntToFloat: return "EOpConvIntToFloat";
case EOpConvIntToDouble: return "EOpConvIntToDouble";
case EOpConvUintToFloat16: return "EOpConvUintToFloat16";
case EOpConvUintToFloat: return "EOpConvUintToFloat";
case EOpConvUintToDouble: return "EOpConvUintToDouble";
case EOpConvInt64ToInt8: return "EOpConvInt64ToInt8";
case EOpConvInt64ToInt16: return "EOpConvInt64ToInt16";
case EOpConvInt64ToInt: return "EOpConvInt64ToInt";
case EOpConvInt64ToUint8: return "EOpConvInt64ToUint8";
case EOpConvInt64ToUint16: return "EOpConvInt64ToUint16";
case EOpConvInt64ToUint: return "EOpConvInt64ToUint";
case EOpConvInt64ToUint64: return "EOpConvInt64ToUint64";
case EOpConvUint64ToInt8: return "EOpConvUint64ToInt8";
case EOpConvUint64ToInt16: return "EOpConvUint64ToInt16";
case EOpConvUint64ToInt: return "EOpConvUint64ToInt";
case EOpConvUint64ToInt64: return "EOpConvUint64ToInt64";
case EOpConvUint64ToUint8: return "EOpConvUint64ToUint8";
case EOpConvUint64ToUint16: return "EOpConvUint64ToUint16";
case EOpConvUint64ToUint: return "EOpConvUint64ToUint";
case EOpConvInt64ToFloat16: return "EOpConvInt64ToFloat16";
case EOpConvInt64ToFloat: return "EOpConvInt64ToFloat";
case EOpConvInt64ToDouble: return "EOpConvInt64ToDouble";
case EOpConvUint64ToFloat16: return "EOpConvUint64ToFloat16";
case EOpConvUint64ToFloat: return "EOpConvUint64ToFloat";
case EOpConvUint64ToDouble: return "EOpConvUint64ToDouble";
case EOpConvFloat16ToInt8: return "EOpConvFloat16ToInt8";
case EOpConvFloat16ToInt16: return "EOpConvFloat16ToInt16";
case EOpConvFloat16ToInt: return "EOpConvFloat16ToInt";
case EOpConvFloat16ToInt64: return "EOpConvFloat16ToInt64";
case EOpConvFloat16ToUint8: return "EOpConvFloat16ToUint8";
case EOpConvFloat16ToUint16: return "EOpConvFloat16ToUint16";
case EOpConvFloat16ToUint: return "EOpConvFloat16ToUint";
case EOpConvFloat16ToUint64: return "EOpConvFloat16ToUint64";
case EOpConvFloat16ToFloat: return "EOpConvFloat16ToFloat";
case EOpConvFloat16ToDouble: return "EOpConvFloat16ToDouble";
case EOpConvFloatToInt8: return "EOpConvFloatToInt8";
case EOpConvFloatToInt16: return "EOpConvFloatToInt16";
case EOpConvFloatToInt: return "EOpConvFloatToInt";
case EOpConvFloatToInt64: return "EOpConvFloatToInt64";
case EOpConvFloatToUint8: return "EOpConvFloatToUint8";
case EOpConvFloatToUint16: return "EOpConvFloatToUint16";
case EOpConvFloatToUint: return "EOpConvFloatToUint";
case EOpConvFloatToUint64: return "EOpConvFloatToUint64";
case EOpConvFloatToFloat16: return "EOpConvFloatToFloat16";
case EOpConvFloatToDouble: return "EOpConvFloatToDouble";
case EOpConvDoubleToInt8: return "EOpConvDoubleToInt8";
case EOpConvDoubleToInt16: return "EOpConvDoubleToInt16";
case EOpConvDoubleToInt: return "EOpConvDoubleToInt";
case EOpConvDoubleToInt64: return "EOpConvDoubleToInt64";
case EOpConvDoubleToUint8: return "EOpConvDoubleToUint8";
case EOpConvDoubleToUint16: return "EOpConvDoubleToUint16";
case EOpConvDoubleToUint: return "EOpConvDoubleToUint";
case EOpConvDoubleToUint64: return "EOpConvDoubleToUint64";
case EOpConvDoubleToFloat16: return "EOpConvDoubleToFloat16";
case EOpConvDoubleToFloat: return "EOpConvDoubleToFloat";
case EOpConvUint64ToPtr: return "EOpConvUint64ToPtr";
case EOpConvPtrToUint64: return "EOpConvPtrToUint64";
case EOpConvUvec2ToPtr: return "EOpConvUvec2ToPtr";
case EOpConvPtrToUvec2: return "EOpConvPtrToUvec2";
case EOpConvUint64ToAccStruct: return "EOpConvUint64ToAccStruct";
case EOpConvUvec2ToAccStruct: return "EOpConvUvec2ToAccStruct";
case EOpAdd: return "EOpAdd";
case EOpSub: return "EOpSub";
case EOpMul: return "EOpMul";
case EOpDiv: return "EOpDiv";
case EOpMod: return "EOpMod";
case EOpRightShift: return "EOpRightShift";
case EOpLeftShift: return "EOpLeftShift";
case EOpAnd: return "EOpAnd";
case EOpInclusiveOr: return "EOpInclusiveOr";
case EOpExclusiveOr: return "EOpExclusiveOr";
case EOpEqual: return "EOpEqual";
case EOpNotEqual: return "EOpNotEqual";
case EOpVectorEqual: return "EOpVectorEqual";
case EOpVectorNotEqual: return "EOpVectorNotEqual";
case EOpLessThan: return "EOpLessThan";
case EOpGreaterThan: return "EOpGreaterThan";
case EOpLessThanEqual: return "EOpLessThanEqual";
case EOpGreaterThanEqual: return "EOpGreaterThanEqual";
case EOpComma: return "EOpComma";
case EOpVectorTimesScalar: return "EOpVectorTimesScalar";
case EOpVectorTimesMatrix: return "EOpVectorTimesMatrix";
case EOpMatrixTimesVector: return "EOpMatrixTimesVector";
case EOpMatrixTimesScalar: return "EOpMatrixTimesScalar";
case EOpLogicalOr: return "EOpLogicalOr";
case EOpLogicalXor: return "EOpLogicalXor";
case EOpLogicalAnd: return "EOpLogicalAnd";
case EOpIndexDirect: return "EOpIndexDirect";
case EOpIndexIndirect: return "EOpIndexIndirect";
case EOpIndexDirectStruct: return "EOpIndexDirectStruct";
case EOpVectorSwizzle: return "EOpVectorSwizzle";
case EOpMethod: return "EOpMethod";
case EOpScoping: return "EOpScoping";
case EOpRadians: return "EOpRadians";
case EOpDegrees: return "EOpDegrees";
case EOpSin: return "EOpSin";
case EOpCos: return "EOpCos";
case EOpTan: return "EOpTan";
case EOpAsin: return "EOpAsin";
case EOpAcos: return "EOpAcos";
case EOpAtan: return "EOpAtan";
case EOpSinh: return "EOpSinh";
case EOpCosh: return "EOpCosh";
case EOpTanh: return "EOpTanh";
case EOpAsinh: return "EOpAsinh";
case EOpAcosh: return "EOpAcosh";
case EOpAtanh: return "EOpAtanh";
case EOpPow: return "EOpPow";
case EOpExp: return "EOpExp";
case EOpLog: return "EOpLog";
case EOpExp2: return "EOpExp2";
case EOpLog2: return "EOpLog2";
case EOpSqrt: return "EOpSqrt";
case EOpInverseSqrt: return "EOpInverseSqrt";
case EOpAbs: return "EOpAbs";
case EOpSign: return "EOpSign";
case EOpFloor: return "EOpFloor";
case EOpTrunc: return "EOpTrunc";
case EOpRound: return "EOpRound";
case EOpRoundEven: return "EOpRoundEven";
case EOpCeil: return "EOpCeil";
case EOpFract: return "EOpFract";
case EOpModf: return "EOpModf";
case EOpMin: return "EOpMin";
case EOpMax: return "EOpMax";
case EOpClamp: return "EOpClamp";
case EOpMix: return "EOpMix";
case EOpStep: return "EOpStep";
case EOpSmoothStep: return "EOpSmoothStep";
case EOpIsNan: return "EOpIsNan";
case EOpIsInf: return "EOpIsInf";
case EOpFma: return "EOpFma";
case EOpFrexp: return "EOpFrexp";
case EOpLdexp: return "EOpLdexp";
case EOpFloatBitsToInt: return "EOpFloatBitsToInt";
case EOpFloatBitsToUint: return "EOpFloatBitsToUint";
case EOpIntBitsToFloat: return "EOpIntBitsToFloat";
case EOpUintBitsToFloat: return "EOpUintBitsToFloat";
case EOpDoubleBitsToInt64: return "EOpDoubleBitsToInt64";
case EOpDoubleBitsToUint64: return "EOpDoubleBitsToUint64";
case EOpInt64BitsToDouble: return "EOpInt64BitsToDouble";
case EOpUint64BitsToDouble: return "EOpUint64BitsToDouble";
case EOpFloat16BitsToInt16: return "EOpFloat16BitsToInt16";
case EOpFloat16BitsToUint16: return "EOpFloat16BitsToUint16";
case EOpInt16BitsToFloat16: return "EOpInt16BitsToFloat16";
case EOpUint16BitsToFloat16: return "EOpUint16BitsToFloat16";
case EOpPackSnorm2x16: return "EOpPackSnorm2x16";
case EOpUnpackSnorm2x16: return "EOpUnpackSnorm2x16";
case EOpPackUnorm2x16: return "EOpPackUnorm2x16";
case EOpUnpackUnorm2x16: return "EOpUnpackUnorm2x16";
case EOpPackSnorm4x8: return "EOpPackSnorm4x8";
case EOpUnpackSnorm4x8: return "EOpUnpackSnorm4x8";
case EOpPackUnorm4x8: return "EOpPackUnorm4x8";
case EOpUnpackUnorm4x8: return "EOpUnpackUnorm4x8";
case EOpPackHalf2x16: return "EOpPackHalf2x16";
case EOpUnpackHalf2x16: return "EOpUnpackHalf2x16";
case EOpPackDouble2x32: return "EOpPackDouble2x32";
case EOpUnpackDouble2x32: return "EOpUnpackDouble2x32";
case EOpPackInt2x32: return "EOpPackInt2x32";
case EOpUnpackInt2x32: return "EOpUnpackInt2x32";
case EOpPackUint2x32: return "EOpPackUint2x32";
case EOpUnpackUint2x32: return "EOpUnpackUint2x32";
case EOpPackFloat2x16: return "EOpPackFloat2x16";
case EOpUnpackFloat2x16: return "EOpUnpackFloat2x16";
case EOpPackInt2x16: return "EOpPackInt2x16";
case EOpUnpackInt2x16: return "EOpUnpackInt2x16";
case EOpPackUint2x16: return "EOpPackUint2x16";
case EOpUnpackUint2x16: return "EOpUnpackUint2x16";
case EOpPackInt4x16: return "EOpPackInt4x16";
case EOpUnpackInt4x16: return "EOpUnpackInt4x16";
case EOpPackUint4x16: return "EOpPackUint4x16";
case EOpUnpackUint4x16: return "EOpUnpackUint4x16";
case EOpPack16: return "EOpPack16";
case EOpPack32: return "EOpPack32";
case EOpPack64: return "EOpPack64";
case EOpUnpack32: return "EOpUnpack32";
case EOpUnpack16: return "EOpUnpack16";
case EOpUnpack8: return "EOpUnpack8";
case EOpLength: return "EOpLength";
case EOpDistance: return "EOpDistance";
case EOpDot: return "EOpDot";
case EOpCross: return "EOpCross";
case EOpNormalize: return "EOpNormalize";
case EOpFaceForward: return "EOpFaceForward";
case EOpReflect: return "EOpReflect";
case EOpRefract: return "EOpRefract";
case EOpMin3: return "EOpMin3";
case EOpMax3: return "EOpMax3";
case EOpMid3: return "EOpMid3";
case EOpDPdx: return "EOpDPdx";
case EOpDPdy: return "EOpDPdy";
case EOpFwidth: return "EOpFwidth";
case EOpDPdxFine: return "EOpDPdxFine";
case EOpDPdyFine: return "EOpDPdyFine";
case EOpFwidthFine: return "EOpFwidthFine";
case EOpDPdxCoarse: return "EOpDPdxCoarse";
case EOpDPdyCoarse: return "EOpDPdyCoarse";
case EOpFwidthCoarse: return "EOpFwidthCoarse";
case EOpInterpolateAtCentroid: return "EOpInterpolateAtCentroid";
case EOpInterpolateAtSample: return "EOpInterpolateAtSample";
case EOpInterpolateAtOffset: return "EOpInterpolateAtOffset";
case EOpInterpolateAtVertex: return "EOpInterpolateAtVertex";
case EOpMatrixTimesMatrix: return "EOpMatrixTimesMatrix";
case EOpOuterProduct: return "EOpOuterProduct";
case EOpDeterminant: return "EOpDeterminant";
case EOpMatrixInverse: return "EOpMatrixInverse";
case EOpTranspose: return "EOpTranspose";
case EOpFtransform: return "EOpFtransform";
case EOpNoise: return "EOpNoise";
case EOpEmitVertex: return "EOpEmitVertex";
case EOpEndPrimitive: return "EOpEndPrimitive";
case EOpEmitStreamVertex: return "EOpEmitStreamVertex";
case EOpEndStreamPrimitive: return "EOpEndStreamPrimitive";
case EOpBarrier: return "EOpBarrier";
case EOpMemoryBarrier: return "EOpMemoryBarrier";
case EOpMemoryBarrierAtomicCounter: return "EOpMemoryBarrierAtomicCounter";
case EOpMemoryBarrierBuffer: return "EOpMemoryBarrierBuffer";
case EOpMemoryBarrierImage: return "EOpMemoryBarrierImage";
case EOpMemoryBarrierShared: return "EOpMemoryBarrierShared";
case EOpGroupMemoryBarrier: return "EOpGroupMemoryBarrier";
case EOpBallot: return "EOpBallot";
case EOpReadInvocation: return "EOpReadInvocation";
case EOpReadFirstInvocation: return "EOpReadFirstInvocation";
case EOpAnyInvocation: return "EOpAnyInvocation";
case EOpAllInvocations: return "EOpAllInvocations";
case EOpAllInvocationsEqual: return "EOpAllInvocationsEqual";
case EOpSubgroupGuardStart: return "EOpSubgroupGuardStart";
case EOpSubgroupBarrier: return "EOpSubgroupBarrier";
case EOpSubgroupMemoryBarrier: return "EOpSubgroupMemoryBarrier";
case EOpSubgroupMemoryBarrierBuffer: return "EOpSubgroupMemoryBarrierBuffer";
case EOpSubgroupMemoryBarrierImage: return "EOpSubgroupMemoryBarrierImage";
case EOpSubgroupMemoryBarrierShared: return "EOpSubgroupMemoryBarrierShared";
case EOpSubgroupElect: return "EOpSubgroupElect";
case EOpSubgroupAll: return "EOpSubgroupAll";
case EOpSubgroupAny: return "EOpSubgroupAny";
case EOpSubgroupAllEqual: return "EOpSubgroupAllEqual";
case EOpSubgroupBroadcast: return "EOpSubgroupBroadcast";
case EOpSubgroupBroadcastFirst: return "EOpSubgroupBroadcastFirst";
case EOpSubgroupBallot: return "EOpSubgroupBallot";
case EOpSubgroupInverseBallot: return "EOpSubgroupInverseBallot";
case EOpSubgroupBallotBitExtract: return "EOpSubgroupBallotBitExtract";
case EOpSubgroupBallotBitCount: return "EOpSubgroupBallotBitCount";
case EOpSubgroupBallotInclusiveBitCount: return "EOpSubgroupBallotInclusiveBitCount";
case EOpSubgroupBallotExclusiveBitCount: return "EOpSubgroupBallotExclusiveBitCount";
case EOpSubgroupBallotFindLSB: return "EOpSubgroupBallotFindLSB";
case EOpSubgroupBallotFindMSB: return "EOpSubgroupBallotFindMSB";
case EOpSubgroupShuffle: return "EOpSubgroupShuffle";
case EOpSubgroupShuffleXor: return "EOpSubgroupShuffleXor";
case EOpSubgroupShuffleUp: return "EOpSubgroupShuffleUp";
case EOpSubgroupShuffleDown: return "EOpSubgroupShuffleDown";
case EOpSubgroupAdd: return "EOpSubgroupAdd";
case EOpSubgroupMul: return "EOpSubgroupMul";
case EOpSubgroupMin: return "EOpSubgroupMin";
case EOpSubgroupMax: return "EOpSubgroupMax";
case EOpSubgroupAnd: return "EOpSubgroupAnd";
case EOpSubgroupOr: return "EOpSubgroupOr";
case EOpSubgroupXor: return "EOpSubgroupXor";
case EOpSubgroupInclusiveAdd: return "EOpSubgroupInclusiveAdd";
case EOpSubgroupInclusiveMul: return "EOpSubgroupInclusiveMul";
case EOpSubgroupInclusiveMin: return "EOpSubgroupInclusiveMin";
case EOpSubgroupInclusiveMax: return "EOpSubgroupInclusiveMax";
case EOpSubgroupInclusiveAnd: return "EOpSubgroupInclusiveAnd";
case EOpSubgroupInclusiveOr: return "EOpSubgroupInclusiveOr";
case EOpSubgroupInclusiveXor: return "EOpSubgroupInclusiveXor";
case EOpSubgroupExclusiveAdd: return "EOpSubgroupExclusiveAdd";
case EOpSubgroupExclusiveMul: return "EOpSubgroupExclusiveMul";
case EOpSubgroupExclusiveMin: return "EOpSubgroupExclusiveMin";
case EOpSubgroupExclusiveMax: return "EOpSubgroupExclusiveMax";
case EOpSubgroupExclusiveAnd: return "EOpSubgroupExclusiveAnd";
case EOpSubgroupExclusiveOr: return "EOpSubgroupExclusiveOr";
case EOpSubgroupExclusiveXor: return "EOpSubgroupExclusiveXor";
case EOpSubgroupClusteredAdd: return "EOpSubgroupClusteredAdd";
case EOpSubgroupClusteredMul: return "EOpSubgroupClusteredMul";
case EOpSubgroupClusteredMin: return "EOpSubgroupClusteredMin";
case EOpSubgroupClusteredMax: return "EOpSubgroupClusteredMax";
case EOpSubgroupClusteredAnd: return "EOpSubgroupClusteredAnd";
case EOpSubgroupClusteredOr: return "EOpSubgroupClusteredOr";
case EOpSubgroupClusteredXor: return "EOpSubgroupClusteredXor";
case EOpSubgroupQuadBroadcast: return "EOpSubgroupQuadBroadcast";
case EOpSubgroupQuadSwapHorizontal: return "EOpSubgroupQuadSwapHorizontal";
case EOpSubgroupQuadSwapVertical: return "EOpSubgroupQuadSwapVertical";
case EOpSubgroupQuadSwapDiagonal: return "EOpSubgroupQuadSwapDiagonal";
case EOpSubgroupPartition: return "EOpSubgroupPartition";
case EOpSubgroupPartitionedAdd: return "EOpSubgroupPartitionedAdd";
case EOpSubgroupPartitionedMul: return "EOpSubgroupPartitionedMul";
case EOpSubgroupPartitionedMin: return "EOpSubgroupPartitionedMin";
case EOpSubgroupPartitionedMax: return "EOpSubgroupPartitionedMax";
case EOpSubgroupPartitionedAnd: return "EOpSubgroupPartitionedAnd";
case EOpSubgroupPartitionedOr: return "EOpSubgroupPartitionedOr";
case EOpSubgroupPartitionedXor: return "EOpSubgroupPartitionedXor";
case EOpSubgroupPartitionedInclusiveAdd: return "EOpSubgroupPartitionedInclusiveAdd";
case EOpSubgroupPartitionedInclusiveMul: return "EOpSubgroupPartitionedInclusiveMul";
case EOpSubgroupPartitionedInclusiveMin: return "EOpSubgroupPartitionedInclusiveMin";
case EOpSubgroupPartitionedInclusiveMax: return "EOpSubgroupPartitionedInclusiveMax";
case EOpSubgroupPartitionedInclusiveAnd: return "EOpSubgroupPartitionedInclusiveAnd";
case EOpSubgroupPartitionedInclusiveOr: return "EOpSubgroupPartitionedInclusiveOr";
case EOpSubgroupPartitionedInclusiveXor: return "EOpSubgroupPartitionedInclusiveXor";
case EOpSubgroupPartitionedExclusiveAdd: return "EOpSubgroupPartitionedExclusiveAdd";
case EOpSubgroupPartitionedExclusiveMul: return "EOpSubgroupPartitionedExclusiveMul";
case EOpSubgroupPartitionedExclusiveMin: return "EOpSubgroupPartitionedExclusiveMin";
case EOpSubgroupPartitionedExclusiveMax: return "EOpSubgroupPartitionedExclusiveMax";
case EOpSubgroupPartitionedExclusiveAnd: return "EOpSubgroupPartitionedExclusiveAnd";
case EOpSubgroupPartitionedExclusiveOr: return "EOpSubgroupPartitionedExclusiveOr";
case EOpSubgroupPartitionedExclusiveXor: return "EOpSubgroupPartitionedExclusiveXor";
case EOpSubgroupGuardStop: return "EOpSubgroupGuardStop";
case EOpMinInvocations: return "EOpMinInvocations";
case EOpMaxInvocations: return "EOpMaxInvocations";
case EOpAddInvocations: return "EOpAddInvocations";
case EOpMinInvocationsNonUniform: return "EOpMinInvocationsNonUniform";
case EOpMaxInvocationsNonUniform: return "EOpMaxInvocationsNonUniform";
case EOpAddInvocationsNonUniform: return "EOpAddInvocationsNonUniform";
case EOpMinInvocationsInclusiveScan: return "EOpMinInvocationsInclusiveScan";
case EOpMaxInvocationsInclusiveScan: return "EOpMaxInvocationsInclusiveScan";
case EOpAddInvocationsInclusiveScan: return "EOpAddInvocationsInclusiveScan";
case EOpMinInvocationsInclusiveScanNonUniform: return "EOpMinInvocationsInclusiveScanNonUniform";
case EOpMaxInvocationsInclusiveScanNonUniform: return "EOpMaxInvocationsInclusiveScanNonUniform";
case EOpAddInvocationsInclusiveScanNonUniform: return "EOpAddInvocationsInclusiveScanNonUniform";
case EOpMinInvocationsExclusiveScan: return "EOpMinInvocationsExclusiveScan";
case EOpMaxInvocationsExclusiveScan: return "EOpMaxInvocationsExclusiveScan";
case EOpAddInvocationsExclusiveScan: return "EOpAddInvocationsExclusiveScan";
case EOpMinInvocationsExclusiveScanNonUniform: return "EOpMinInvocationsExclusiveScanNonUniform";
case EOpMaxInvocationsExclusiveScanNonUniform: return "EOpMaxInvocationsExclusiveScanNonUniform";
case EOpAddInvocationsExclusiveScanNonUniform: return "EOpAddInvocationsExclusiveScanNonUniform";
case EOpSwizzleInvocations: return "EOpSwizzleInvocations";
case EOpSwizzleInvocationsMasked: return "EOpSwizzleInvocationsMasked";
case EOpWriteInvocation: return "EOpWriteInvocation";
case EOpMbcnt: return "EOpMbcnt";
case EOpCubeFaceIndex: return "EOpCubeFaceIndex";
case EOpCubeFaceCoord: return "EOpCubeFaceCoord";
case EOpTime: return "EOpTime";
case EOpAtomicAdd: return "EOpAtomicAdd";
case EOpAtomicSubtract: return "EOpAtomicSubtract";
case EOpAtomicMin: return "EOpAtomicMin";
case EOpAtomicMax: return "EOpAtomicMax";
case EOpAtomicAnd: return "EOpAtomicAnd";
case EOpAtomicOr: return "EOpAtomicOr";
case EOpAtomicXor: return "EOpAtomicXor";
case EOpAtomicExchange: return "EOpAtomicExchange";
case EOpAtomicCompSwap: return "EOpAtomicCompSwap";
case EOpAtomicLoad: return "EOpAtomicLoad";
case EOpAtomicStore: return "EOpAtomicStore";
case EOpAtomicCounterIncrement: return "EOpAtomicCounterIncrement";
case EOpAtomicCounterDecrement: return "EOpAtomicCounterDecrement";
case EOpAtomicCounter: return "EOpAtomicCounter";
case EOpAtomicCounterAdd: return "EOpAtomicCounterAdd";
case EOpAtomicCounterSubtract: return "EOpAtomicCounterSubtract";
case EOpAtomicCounterMin: return "EOpAtomicCounterMin";
case EOpAtomicCounterMax: return "EOpAtomicCounterMax";
case EOpAtomicCounterAnd: return "EOpAtomicCounterAnd";
case EOpAtomicCounterOr: return "EOpAtomicCounterOr";
case EOpAtomicCounterXor: return "EOpAtomicCounterXor";
case EOpAtomicCounterExchange: return "EOpAtomicCounterExchange";
case EOpAtomicCounterCompSwap: return "EOpAtomicCounterCompSwap";
case EOpAny: return "EOpAny";
case EOpAll: return "EOpAll";
case EOpCooperativeMatrixLoad: return "EOpCooperativeMatrixLoad";
case EOpCooperativeMatrixStore: return "EOpCooperativeMatrixStore";
case EOpCooperativeMatrixMulAdd: return "EOpCooperativeMatrixMulAdd";
case EOpCooperativeMatrixLoadNV: return "EOpCooperativeMatrixLoadNV";
case EOpCooperativeMatrixStoreNV: return "EOpCooperativeMatrixStoreNV";
case EOpCooperativeMatrixMulAddNV: return "EOpCooperativeMatrixMulAddNV";
case EOpBeginInvocationInterlock: return "EOpBeginInvocationInterlock";
case EOpEndInvocationInterlock: return "EOpEndInvocationInterlock";
case EOpIsHelperInvocation: return "EOpIsHelperInvocation";
case EOpDebugPrintf: return "EOpDebugPrintf";
case EOpKill: return "EOpKill";
case EOpTerminateInvocation: return "EOpTerminateInvocation";
case EOpDemote: return "EOpDemote";
case EOpTerminateRayKHR: return "EOpTerminateRayKHR";
case EOpIgnoreIntersectionKHR: return "EOpIgnoreIntersectionKHR";
case EOpReturn: return "EOpReturn";
case EOpBreak: return "EOpBreak";
case EOpContinue: return "EOpContinue";
case EOpCase: return "EOpCase";
case EOpDefault: return "EOpDefault";
case EOpConstructGuardStart: return "EOpConstructGuardStart";
case EOpConstructInt: return "EOpConstructInt";
case EOpConstructUint: return "EOpConstructUint";
case EOpConstructInt8: return "EOpConstructInt8";
case EOpConstructUint8: return "EOpConstructUint8";
case EOpConstructInt16: return "EOpConstructInt16";
case EOpConstructUint16: return "EOpConstructUint16";
case EOpConstructInt64: return "EOpConstructInt64";
case EOpConstructUint64: return "EOpConstructUint64";
case EOpConstructBool: return "EOpConstructBool";
case EOpConstructFloat: return "EOpConstructFloat";
case EOpConstructDouble: return "EOpConstructDouble";
case EOpConstructVec2: return "EOpConstructVec2";
case EOpConstructVec3: return "EOpConstructVec3";
case EOpConstructVec4: return "EOpConstructVec4";
case EOpConstructMat2x2: return "EOpConstructMat2x2";
case EOpConstructMat2x3: return "EOpConstructMat2x3";
case EOpConstructMat2x4: return "EOpConstructMat2x4";
case EOpConstructMat3x2: return "EOpConstructMat3x2";
case EOpConstructMat3x3: return "EOpConstructMat3x3";
case EOpConstructMat3x4: return "EOpConstructMat3x4";
case EOpConstructMat4x2: return "EOpConstructMat4x2";
case EOpConstructMat4x3: return "EOpConstructMat4x3";
case EOpConstructMat4x4: return "EOpConstructMat4x4";
case EOpConstructDVec2: return "EOpConstructDVec2";
case EOpConstructDVec3: return "EOpConstructDVec3";
case EOpConstructDVec4: return "EOpConstructDVec4";
case EOpConstructBVec2: return "EOpConstructBVec2";
case EOpConstructBVec3: return "EOpConstructBVec3";
case EOpConstructBVec4: return "EOpConstructBVec4";
case EOpConstructI8Vec2: return "EOpConstructI8Vec2";
case EOpConstructI8Vec3: return "EOpConstructI8Vec3";
case EOpConstructI8Vec4: return "EOpConstructI8Vec4";
case EOpConstructU8Vec2: return "EOpConstructU8Vec2";
case EOpConstructU8Vec3: return "EOpConstructU8Vec3";
case EOpConstructU8Vec4: return "EOpConstructU8Vec4";
case EOpConstructI16Vec2: return "EOpConstructI16Vec2";
case EOpConstructI16Vec3: return "EOpConstructI16Vec3";
case EOpConstructI16Vec4: return "EOpConstructI16Vec4";
case EOpConstructU16Vec2: return "EOpConstructU16Vec2";
case EOpConstructU16Vec3: return "EOpConstructU16Vec3";
case EOpConstructU16Vec4: return "EOpConstructU16Vec4";
case EOpConstructIVec2: return "EOpConstructIVec2";
case EOpConstructIVec3: return "EOpConstructIVec3";
case EOpConstructIVec4: return "EOpConstructIVec4";
case EOpConstructUVec2: return "EOpConstructUVec2";
case EOpConstructUVec3: return "EOpConstructUVec3";
case EOpConstructUVec4: return "EOpConstructUVec4";
case EOpConstructI64Vec2: return "EOpConstructI64Vec2";
case EOpConstructI64Vec3: return "EOpConstructI64Vec3";
case EOpConstructI64Vec4: return "EOpConstructI64Vec4";
case EOpConstructU64Vec2: return "EOpConstructU64Vec2";
case EOpConstructU64Vec3: return "EOpConstructU64Vec3";
case EOpConstructU64Vec4: return "EOpConstructU64Vec4";
case EOpConstructDMat2x2: return "EOpConstructDMat2x2";
case EOpConstructDMat2x3: return "EOpConstructDMat2x3";
case EOpConstructDMat2x4: return "EOpConstructDMat2x4";
case EOpConstructDMat3x2: return "EOpConstructDMat3x2";
case EOpConstructDMat3x3: return "EOpConstructDMat3x3";
case EOpConstructDMat3x4: return "EOpConstructDMat3x4";
case EOpConstructDMat4x2: return "EOpConstructDMat4x2";
case EOpConstructDMat4x3: return "EOpConstructDMat4x3";
case EOpConstructDMat4x4: return "EOpConstructDMat4x4";
case EOpConstructIMat2x2: return "EOpConstructIMat2x2";
case EOpConstructIMat2x3: return "EOpConstructIMat2x3";
case EOpConstructIMat2x4: return "EOpConstructIMat2x4";
case EOpConstructIMat3x2: return "EOpConstructIMat3x2";
case EOpConstructIMat3x3: return "EOpConstructIMat3x3";
case EOpConstructIMat3x4: return "EOpConstructIMat3x4";
case EOpConstructIMat4x2: return "EOpConstructIMat4x2";
case EOpConstructIMat4x3: return "EOpConstructIMat4x3";
case EOpConstructIMat4x4: return "EOpConstructIMat4x4";
case EOpConstructUMat2x2: return "EOpConstructUMat2x2";
case EOpConstructUMat2x3: return "EOpConstructUMat2x3";
case EOpConstructUMat2x4: return "EOpConstructUMat2x4";
case EOpConstructUMat3x2: return "EOpConstructUMat3x2";
case EOpConstructUMat3x3: return "EOpConstructUMat3x3";
case EOpConstructUMat3x4: return "EOpConstructUMat3x4";
case EOpConstructUMat4x2: return "EOpConstructUMat4x2";
case EOpConstructUMat4x3: return "EOpConstructUMat4x3";
case EOpConstructUMat4x4: return "EOpConstructUMat4x4";
case EOpConstructBMat2x2: return "EOpConstructBMat2x2";
case EOpConstructBMat2x3: return "EOpConstructBMat2x3";
case EOpConstructBMat2x4: return "EOpConstructBMat2x4";
case EOpConstructBMat3x2: return "EOpConstructBMat3x2";
case EOpConstructBMat3x3: return "EOpConstructBMat3x3";
case EOpConstructBMat3x4: return "EOpConstructBMat3x4";
case EOpConstructBMat4x2: return "EOpConstructBMat4x2";
case EOpConstructBMat4x3: return "EOpConstructBMat4x3";
case EOpConstructBMat4x4: return "EOpConstructBMat4x4";
case EOpConstructFloat16: return "EOpConstructFloat16";
case EOpConstructF16Vec2: return "EOpConstructF16Vec2";
case EOpConstructF16Vec3: return "EOpConstructF16Vec3";
case EOpConstructF16Vec4: return "EOpConstructF16Vec4";
case EOpConstructF16Mat2x2: return "EOpConstructF16Mat2x2";
case EOpConstructF16Mat2x3: return "EOpConstructF16Mat2x3";
case EOpConstructF16Mat2x4: return "EOpConstructF16Mat2x4";
case EOpConstructF16Mat3x2: return "EOpConstructF16Mat3x2";
case EOpConstructF16Mat3x3: return "EOpConstructF16Mat3x3";
case EOpConstructF16Mat3x4: return "EOpConstructF16Mat3x4";
case EOpConstructF16Mat4x2: return "EOpConstructF16Mat4x2";
case EOpConstructF16Mat4x3: return "EOpConstructF16Mat4x3";
case EOpConstructF16Mat4x4: return "EOpConstructF16Mat4x4";
case EOpConstructStruct: return "EOpConstructStruct";
case EOpConstructTextureSampler: return "EOpConstructTextureSampler";
case EOpConstructNonuniform: return "EOpConstructNonuniform";
case EOpConstructReference: return "EOpConstructReference";
case EOpConstructCooperativeMatrixNV: return "EOpConstructCooperativeMatrixNV";
case EOpConstructCooperativeMatrixKHR: return "EOpConstructCooperativeMatrixKHR";
case EOpConstructAccStruct: return "EOpConstructAccStruct";
case EOpConstructGuardEnd: return "EOpConstructGuardEnd";
case EOpAssign: return "EOpAssign";
case EOpAddAssign: return "EOpAddAssign";
case EOpSubAssign: return "EOpSubAssign";
case EOpMulAssign: return "EOpMulAssign";
case EOpVectorTimesMatrixAssign: return "EOpVectorTimesMatrixAssign";
case EOpVectorTimesScalarAssign: return "EOpVectorTimesScalarAssign";
case EOpMatrixTimesScalarAssign: return "EOpMatrixTimesScalarAssign";
case EOpMatrixTimesMatrixAssign: return "EOpMatrixTimesMatrixAssign";
case EOpDivAssign: return "EOpDivAssign";
case EOpModAssign: return "EOpModAssign";
case EOpAndAssign: return "EOpAndAssign";
case EOpInclusiveOrAssign: return "EOpInclusiveOrAssign";
case EOpExclusiveOrAssign: return "EOpExclusiveOrAssign";
case EOpLeftShiftAssign: return "EOpLeftShiftAssign";
case EOpRightShiftAssign: return "EOpRightShiftAssign";
case EOpArrayLength: return "EOpArrayLength";
case EOpImageGuardBegin: return "EOpImageGuardBegin";
case EOpImageQuerySize: return "EOpImageQuerySize";
case EOpImageQuerySamples: return "EOpImageQuerySamples";
case EOpImageLoad: return "EOpImageLoad";
case EOpImageStore: return "EOpImageStore";
case EOpImageLoadLod: return "EOpImageLoadLod";
case EOpImageStoreLod: return "EOpImageStoreLod";
case EOpImageAtomicAdd: return "EOpImageAtomicAdd";
case EOpImageAtomicMin: return "EOpImageAtomicMin";
case EOpImageAtomicMax: return "EOpImageAtomicMax";
case EOpImageAtomicAnd: return "EOpImageAtomicAnd";
case EOpImageAtomicOr: return "EOpImageAtomicOr";
case EOpImageAtomicXor: return "EOpImageAtomicXor";
case EOpImageAtomicExchange: return "EOpImageAtomicExchange";
case EOpImageAtomicCompSwap: return "EOpImageAtomicCompSwap";
case EOpImageAtomicLoad: return "EOpImageAtomicLoad";
case EOpImageAtomicStore: return "EOpImageAtomicStore";
case EOpSubpassLoad: return "EOpSubpassLoad";
case EOpSubpassLoadMS: return "EOpSubpassLoadMS";
case EOpSparseImageLoad: return "EOpSparseImageLoad";
case EOpSparseImageLoadLod: return "EOpSparseImageLoadLod";
case EOpColorAttachmentReadEXT: return "EOpColorAttachmentReadEXT";
case EOpImageGuardEnd: return "EOpImageGuardEnd";
case EOpTextureGuardBegin: return "EOpTextureGuardBegin";
case EOpTextureQuerySize: return "EOpTextureQuerySize";
case EOpTextureQueryLod: return "EOpTextureQueryLod";
case EOpTextureQueryLevels: return "EOpTextureQueryLevels";
case EOpTextureQuerySamples: return "EOpTextureQuerySamples";
case EOpSamplingGuardBegin: return "EOpSamplingGuardBegin";
case EOpTexture: return "EOpTexture";
case EOpTextureProj: return "EOpTextureProj";
case EOpTextureLod: return "EOpTextureLod";
case EOpTextureOffset: return "EOpTextureOffset";
case EOpTextureFetch: return "EOpTextureFetch";
case EOpTextureFetchOffset: return "EOpTextureFetchOffset";
case EOpTextureProjOffset: return "EOpTextureProjOffset";
case EOpTextureLodOffset: return "EOpTextureLodOffset";
case EOpTextureProjLod: return "EOpTextureProjLod";
case EOpTextureProjLodOffset: return "EOpTextureProjLodOffset";
case EOpTextureGrad: return "EOpTextureGrad";
case EOpTextureGradOffset: return "EOpTextureGradOffset";
case EOpTextureProjGrad: return "EOpTextureProjGrad";
case EOpTextureProjGradOffset: return "EOpTextureProjGradOffset";
case EOpTextureGather: return "EOpTextureGather";
case EOpTextureGatherOffset: return "EOpTextureGatherOffset";
case EOpTextureGatherOffsets: return "EOpTextureGatherOffsets";
case EOpTextureClamp: return "EOpTextureClamp";
case EOpTextureOffsetClamp: return "EOpTextureOffsetClamp";
case EOpTextureGradClamp: return "EOpTextureGradClamp";
case EOpTextureGradOffsetClamp: return "EOpTextureGradOffsetClamp";
case EOpTextureGatherLod: return "EOpTextureGatherLod";
case EOpTextureGatherLodOffset: return "EOpTextureGatherLodOffset";
case EOpTextureGatherLodOffsets: return "EOpTextureGatherLodOffsets";
case EOpFragmentMaskFetch: return "EOpFragmentMaskFetch";
case EOpFragmentFetch: return "EOpFragmentFetch";
case EOpSparseTextureGuardBegin: return "EOpSparseTextureGuardBegin";
case EOpSparseTexture: return "EOpSparseTexture";
case EOpSparseTextureLod: return "EOpSparseTextureLod";
case EOpSparseTextureOffset: return "EOpSparseTextureOffset";
case EOpSparseTextureFetch: return "EOpSparseTextureFetch";
case EOpSparseTextureFetchOffset: return "EOpSparseTextureFetchOffset";
case EOpSparseTextureLodOffset: return "EOpSparseTextureLodOffset";
case EOpSparseTextureGrad: return "EOpSparseTextureGrad";
case EOpSparseTextureGradOffset: return "EOpSparseTextureGradOffset";
case EOpSparseTextureGather: return "EOpSparseTextureGather";
case EOpSparseTextureGatherOffset: return "EOpSparseTextureGatherOffset";
case EOpSparseTextureGatherOffsets: return "EOpSparseTextureGatherOffsets";
case EOpSparseTexelsResident: return "EOpSparseTexelsResident";
case EOpSparseTextureClamp: return "EOpSparseTextureClamp";
case EOpSparseTextureOffsetClamp: return "EOpSparseTextureOffsetClamp";
case EOpSparseTextureGradClamp: return "EOpSparseTextureGradClamp";
case EOpSparseTextureGradOffsetClamp: return "EOpSparseTextureGradOffsetClamp";
case EOpSparseTextureGatherLod: return "EOpSparseTextureGatherLod";
case EOpSparseTextureGatherLodOffset: return "EOpSparseTextureGatherLodOffset";
case EOpSparseTextureGatherLodOffsets: return "EOpSparseTextureGatherLodOffsets";
case EOpSparseTextureGuardEnd: return "EOpSparseTextureGuardEnd";
case EOpImageFootprintGuardBegin: return "EOpImageFootprintGuardBegin";
case EOpImageSampleFootprintNV: return "EOpImageSampleFootprintNV";
case EOpImageSampleFootprintClampNV: return "EOpImageSampleFootprintClampNV";
case EOpImageSampleFootprintLodNV: return "EOpImageSampleFootprintLodNV";
case EOpImageSampleFootprintGradNV: return "EOpImageSampleFootprintGradNV";
case EOpImageSampleFootprintGradClampNV: return "EOpImageSampleFootprintGradClampNV";
case EOpImageFootprintGuardEnd: return "EOpImageFootprintGuardEnd";
case EOpSamplingGuardEnd: return "EOpSamplingGuardEnd";
case EOpTextureGuardEnd: return "EOpTextureGuardEnd";
case EOpAddCarry: return "EOpAddCarry";
case EOpSubBorrow: return "EOpSubBorrow";
case EOpUMulExtended: return "EOpUMulExtended";
case EOpIMulExtended: return "EOpIMulExtended";
case EOpBitfieldExtract: return "EOpBitfieldExtract";
case EOpBitfieldInsert: return "EOpBitfieldInsert";
case EOpBitFieldReverse: return "EOpBitFieldReverse";
case EOpBitCount: return "EOpBitCount";
case EOpFindLSB: return "EOpFindLSB";
case EOpFindMSB: return "EOpFindMSB";
case EOpCountLeadingZeros: return "EOpCountLeadingZeros";
case EOpCountTrailingZeros: return "EOpCountTrailingZeros";
case EOpAbsDifference: return "EOpAbsDifference";
case EOpAddSaturate: return "EOpAddSaturate";
case EOpSubSaturate: return "EOpSubSaturate";
case EOpAverage: return "EOpAverage";
case EOpAverageRounded: return "EOpAverageRounded";
case EOpMul32x16: return "EOpMul32x16";
case EOpTraceNV: return "EOpTraceNV";
case EOpTraceRayMotionNV: return "EOpTraceRayMotionNV";
case EOpTraceKHR: return "EOpTraceKHR";
case EOpReportIntersection: return "EOpReportIntersection";
case EOpIgnoreIntersectionNV: return "EOpIgnoreIntersectionNV";
case EOpTerminateRayNV: return "EOpTerminateRayNV";
case EOpExecuteCallableNV: return "EOpExecuteCallableNV";
case EOpExecuteCallableKHR: return "EOpExecuteCallableKHR";
case EOpWritePackedPrimitiveIndices4x8NV: return "EOpWritePackedPrimitiveIndices4x8NV";
case EOpEmitMeshTasksEXT: return "EOpEmitMeshTasksEXT";
case EOpSetMeshOutputsEXT: return "EOpSetMeshOutputsEXT";
case EOpRayQueryInitialize: return "EOpRayQueryInitialize";
case EOpRayQueryTerminate: return "EOpRayQueryTerminate";
case EOpRayQueryGenerateIntersection: return "EOpRayQueryGenerateIntersection";
case EOpRayQueryConfirmIntersection: return "EOpRayQueryConfirmIntersection";
case EOpRayQueryProceed: return "EOpRayQueryProceed";
case EOpRayQueryGetIntersectionType: return "EOpRayQueryGetIntersectionType";
case EOpRayQueryGetRayTMin: return "EOpRayQueryGetRayTMin";
case EOpRayQueryGetRayFlags: return "EOpRayQueryGetRayFlags";
case EOpRayQueryGetIntersectionT: return "EOpRayQueryGetIntersectionT";
case EOpRayQueryGetIntersectionInstanceCustomIndex: return "EOpRayQueryGetIntersectionInstanceCustomIndex";
case EOpRayQueryGetIntersectionInstanceId: return "EOpRayQueryGetIntersectionInstanceId";
case EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset: return "EOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffset";
case EOpRayQueryGetIntersectionGeometryIndex: return "EOpRayQueryGetIntersectionGeometryIndex";
case EOpRayQueryGetIntersectionPrimitiveIndex: return "EOpRayQueryGetIntersectionPrimitiveIndex";
case EOpRayQueryGetIntersectionBarycentrics: return "EOpRayQueryGetIntersectionBarycentrics";
case EOpRayQueryGetIntersectionFrontFace: return "EOpRayQueryGetIntersectionFrontFace";
case EOpRayQueryGetIntersectionCandidateAABBOpaque: return "EOpRayQueryGetIntersectionCandidateAABBOpaque";
case EOpRayQueryGetIntersectionObjectRayDirection: return "EOpRayQueryGetIntersectionObjectRayDirection";
case EOpRayQueryGetIntersectionObjectRayOrigin: return "EOpRayQueryGetIntersectionObjectRayOrigin";
case EOpRayQueryGetWorldRayDirection: return "EOpRayQueryGetWorldRayDirection";
case EOpRayQueryGetWorldRayOrigin: return "EOpRayQueryGetWorldRayOrigin";
case EOpRayQueryGetIntersectionObjectToWorld: return "EOpRayQueryGetIntersectionObjectToWorld";
case EOpRayQueryGetIntersectionWorldToObject: return "EOpRayQueryGetIntersectionWorldToObject";
case EOpHitObjectTraceRayNV: return "EOpHitObjectTraceRayNV";
case EOpHitObjectTraceRayMotionNV: return "EOpHitObjectTraceRayMotionNV";
case EOpHitObjectRecordHitNV: return "EOpHitObjectRecordHitNV";
case EOpHitObjectRecordHitMotionNV: return "EOpHitObjectRecordHitMotionNV";
case EOpHitObjectRecordHitWithIndexNV: return "EOpHitObjectRecordHitWithIndexNV";
case EOpHitObjectRecordHitWithIndexMotionNV: return "EOpHitObjectRecordHitWithIndexMotionNV";
case EOpHitObjectRecordMissNV: return "EOpHitObjectRecordMissNV";
case EOpHitObjectRecordMissMotionNV: return "EOpHitObjectRecordMissMotionNV";
case EOpHitObjectRecordEmptyNV: return "EOpHitObjectRecordEmptyNV";
case EOpHitObjectExecuteShaderNV: return "EOpHitObjectExecuteShaderNV";
case EOpHitObjectIsEmptyNV: return "EOpHitObjectIsEmptyNV";
case EOpHitObjectIsMissNV: return "EOpHitObjectIsMissNV";
case EOpHitObjectIsHitNV: return "EOpHitObjectIsHitNV";
case EOpHitObjectGetRayTMinNV: return "EOpHitObjectGetRayTMinNV";
case EOpHitObjectGetRayTMaxNV: return "EOpHitObjectGetRayTMaxNV";
case EOpHitObjectGetObjectRayOriginNV: return "EOpHitObjectGetObjectRayOriginNV";
case EOpHitObjectGetObjectRayDirectionNV: return "EOpHitObjectGetObjectRayDirectionNV";
case EOpHitObjectGetWorldRayOriginNV: return "EOpHitObjectGetWorldRayOriginNV";
case EOpHitObjectGetWorldRayDirectionNV: return "EOpHitObjectGetWorldRayDirectionNV";
case EOpHitObjectGetWorldToObjectNV: return "EOpHitObjectGetWorldToObjectNV";
case EOpHitObjectGetObjectToWorldNV: return "EOpHitObjectGetObjectToWorldNV";
case EOpHitObjectGetInstanceCustomIndexNV: return "EOpHitObjectGetInstanceCustomIndexNV";
case EOpHitObjectGetInstanceIdNV: return "EOpHitObjectGetInstanceIdNV";
case EOpHitObjectGetGeometryIndexNV: return "EOpHitObjectGetGeometryIndexNV";
case EOpHitObjectGetPrimitiveIndexNV: return "EOpHitObjectGetPrimitiveIndexNV";
case EOpHitObjectGetHitKindNV: return "EOpHitObjectGetHitKindNV";
case EOpHitObjectGetShaderBindingTableRecordIndexNV: return "EOpHitObjectGetShaderBindingTableRecordIndexNV";
case EOpHitObjectGetShaderRecordBufferHandleNV: return "EOpHitObjectGetShaderRecordBufferHandleNV";
case EOpHitObjectGetAttributesNV: return "EOpHitObjectGetAttributesNV";
case EOpHitObjectGetCurrentTimeNV: return "EOpHitObjectGetCurrentTimeNV";
case EOpReorderThreadNV: return "EOpReorderThreadNV";
case EOpFetchMicroTriangleVertexPositionNV: return "EOpFetchMicroTriangleVertexPositionNV";
case EOpFetchMicroTriangleVertexBarycentricNV: return "EOpFetchMicroTriangleVertexBarycentricNV";
case EOpClip: return "EOpClip";
case EOpIsFinite: return "EOpIsFinite";
case EOpLog10: return "EOpLog10";
case EOpRcp: return "EOpRcp";
case EOpSaturate: return "EOpSaturate";
case EOpSinCos: return "EOpSinCos";
case EOpGenMul: return "EOpGenMul";
case EOpDst: return "EOpDst";
case EOpInterlockedAdd: return "EOpInterlockedAdd";
case EOpInterlockedAnd: return "EOpInterlockedAnd";
case EOpInterlockedCompareExchange: return "EOpInterlockedCompareExchange";
case EOpInterlockedCompareStore: return "EOpInterlockedCompareStore";
case EOpInterlockedExchange: return "EOpInterlockedExchange";
case EOpInterlockedMax: return "EOpInterlockedMax";
case EOpInterlockedMin: return "EOpInterlockedMin";
case EOpInterlockedOr: return "EOpInterlockedOr";
case EOpInterlockedXor: return "EOpInterlockedXor";
case EOpAllMemoryBarrierWithGroupSync: return "EOpAllMemoryBarrierWithGroupSync";
case EOpDeviceMemoryBarrier: return "EOpDeviceMemoryBarrier";
case EOpDeviceMemoryBarrierWithGroupSync: return "EOpDeviceMemoryBarrierWithGroupSync";
case EOpWorkgroupMemoryBarrier: return "EOpWorkgroupMemoryBarrier";
case EOpWorkgroupMemoryBarrierWithGroupSync: return "EOpWorkgroupMemoryBarrierWithGroupSync";
case EOpEvaluateAttributeSnapped: return "EOpEvaluateAttributeSnapped";
case EOpF32tof16: return "EOpF32tof16";
case EOpF16tof32: return "EOpF16tof32";
case EOpLit: return "EOpLit";
case EOpTextureBias: return "EOpTextureBias";
case EOpAsDouble: return "EOpAsDouble";
case EOpD3DCOLORtoUBYTE4: return "EOpD3DCOLORtoUBYTE4";
case EOpMethodSample: return "EOpMethodSample";
case EOpMethodSampleBias: return "EOpMethodSampleBias";
case EOpMethodSampleCmp: return "EOpMethodSampleCmp";
case EOpMethodSampleCmpLevelZero: return "EOpMethodSampleCmpLevelZero";
case EOpMethodSampleGrad: return "EOpMethodSampleGrad";
case EOpMethodSampleLevel: return "EOpMethodSampleLevel";
case EOpMethodLoad: return "EOpMethodLoad";
case EOpMethodGetDimensions: return "EOpMethodGetDimensions";
case EOpMethodGetSamplePosition: return "EOpMethodGetSamplePosition";
case EOpMethodGather: return "EOpMethodGather";
case EOpMethodCalculateLevelOfDetail: return "EOpMethodCalculateLevelOfDetail";
case EOpMethodCalculateLevelOfDetailUnclamped: return "EOpMethodCalculateLevelOfDetailUnclamped";
case EOpMethodLoad2: return "EOpMethodLoad2";
case EOpMethodLoad3: return "EOpMethodLoad3";
case EOpMethodLoad4: return "EOpMethodLoad4";
case EOpMethodStore: return "EOpMethodStore";
case EOpMethodStore2: return "EOpMethodStore2";
case EOpMethodStore3: return "EOpMethodStore3";
case EOpMethodStore4: return "EOpMethodStore4";
case EOpMethodIncrementCounter: return "EOpMethodIncrementCounter";
case EOpMethodDecrementCounter: return "EOpMethodDecrementCounter";
case EOpMethodConsume: return "EOpMethodConsume";
case EOpMethodGatherRed: return "EOpMethodGatherRed";
case EOpMethodGatherGreen: return "EOpMethodGatherGreen";
case EOpMethodGatherBlue: return "EOpMethodGatherBlue";
case EOpMethodGatherAlpha: return "EOpMethodGatherAlpha";
case EOpMethodGatherCmp: return "EOpMethodGatherCmp";
case EOpMethodGatherCmpRed: return "EOpMethodGatherCmpRed";
case EOpMethodGatherCmpGreen: return "EOpMethodGatherCmpGreen";
case EOpMethodGatherCmpBlue: return "EOpMethodGatherCmpBlue";
case EOpMethodGatherCmpAlpha: return "EOpMethodGatherCmpAlpha";
case EOpMethodAppend: return "EOpMethodAppend";
case EOpMethodRestartStrip: return "EOpMethodRestartStrip";
case EOpMatrixSwizzle: return "EOpMatrixSwizzle";
case EOpWaveGetLaneCount: return "EOpWaveGetLaneCount";
case EOpWaveGetLaneIndex: return "EOpWaveGetLaneIndex";
case EOpWaveActiveCountBits: return "EOpWaveActiveCountBits";
case EOpWavePrefixCountBits: return "EOpWavePrefixCountBits";
case EOpReadClockSubgroupKHR: return "EOpReadClockSubgroupKHR";
case EOpReadClockDeviceKHR: return "EOpReadClockDeviceKHR";
case EOpRayQueryGetIntersectionTriangleVertexPositionsEXT: return "EOpRayQueryGetIntersectionTriangleVertexPositionsEXT";
case EOpStencilAttachmentReadEXT: return "EOpStencilAttachmentReadEXT";
case EOpDepthAttachmentReadEXT: return "EOpDepthAttachmentReadEXT";
case EOpImageSampleWeightedQCOM: return "EOpImageSampleWeightedQCOM";
case EOpImageBoxFilterQCOM: return "EOpImageBoxFilterQCOM";
case EOpImageBlockMatchSADQCOM: return "EOpImageBlockMatchSADQCOM";
case EOpImageBlockMatchSSDQCOM: return "EOpImageBlockMatchSSDQCOM";
}
}
std::string glslangNodeToString(const TIntermNode* node) {
if (auto nodeAsOperator = node->getAsOperator()) {
std::string result;
if (node->getAsAggregate()) {
result = "Aggregate(";
} else if (node->getAsUnaryNode()) {
result = "Unary(";
} else if (node->getAsBinaryNode()) {
result = "Binary(";
} else {
result = "Operator(";
}
result += glslangOperatorToString(nodeAsOperator->getOp());
result += ')';
return result;
}
if (node->getAsLoopNode()) {
return "Loop";
}
if (auto nodeAsBranch = node->getAsBranchNode()) {
return std::string("Branch(") + glslangOperatorToString(nodeAsBranch->getFlowOp()) + ")";
}
if (auto nodeAsSymbol = node->getAsSymbolNode()) {
return std::string("Symbol(") + std::string(nodeAsSymbol->getAccessName()) + ")";
}
if (node->getAsMethodNode()) {
return "Method";
}
if (node->getAsSwitchNode()) {
return "Switch";
}
if (node->getAsSelectionNode()) {
return "Selection";
}
if (auto nodeAsConstantUnion = node->getAsConstantUnion()) {
return "ConstantUnion(size = "
+ std::to_string(nodeAsConstantUnion->getConstArray().size())
+ ", type = "
+ std::string(nodeAsConstantUnion->getType().getCompleteString())
+ ")";
}
if (node->getAsTyped()) {
return "Typed";
}
return "Node";
}
std::string glslangLocToString(const glslang::TSourceLoc& loc) {
return loc.getStringNameOrNum() + ":" + std::to_string(loc.line) + ":" + std::to_string(loc.column);
}
std::string glslangNodeToStringWithLoc(const TIntermNode* node) {
return glslangLocToString(node->getLoc()) + ":" + glslangNodeToString(node);
}
} // namespace astrict
File diff suppressed because it is too large Load Diff
+768
View File
@@ -0,0 +1,768 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <astrict/ToGlsl.h>
#include <astrict/CommonTypes.h>
#include <astrict/DebugCommon.h>
#include <astrict/GlslTypes.h>
#include <sstream>
#include <unordered_set>
#include <utils/Panic.h>
namespace astrict {
constexpr auto kIndentAmount = " ";
constexpr auto kSpace = " ";
constexpr auto kNewline = "\n";
template<typename T>
void dumpVariableOrExpression(
const PackFromGlsl& pack, const Function& function,
T valueId, bool parenthesize, std::ostringstream& out);
void dumpAnyVariableOrExpression(
const PackFromGlsl& pack, const Function& function,
VariableOrExpressionId valueId, bool parenthesize, std::ostringstream& out);
template<typename T>
void dumpExpression(
const PackFromGlsl& pack, const Function& function,
const T& value, bool parenthesize, std::ostringstream& out);
template<typename T>
void dumpExpressionOperandExpression(
const PackFromGlsl& pack, const Function& function,
const T& op, const std::vector<VariableOrExpressionId>& args,
bool parenthesize, std::ostringstream& out);
template<typename T>
void dumpStatement(
const PackFromGlsl& pack, const Function& function, StatementBlockId blockId,
const T& statement, int depth,
std::ostringstream& out);
void dumpBlock(
const PackFromGlsl& pack, const Function& function, StatementBlockId blockId,
int depth, std::ostringstream& out);
void indent(int depth, std::ostringstream& out) {
for (int i = 0; i < depth; ++i) {
out << kIndentAmount;
}
}
void dumpString(const PackFromGlsl& pack, StringId stringId,
std::ostringstream& out) {
ASSERT_PRECONDITION(pack.strings.find(stringId) != pack.strings.end(),
"Missing string");
const auto& string = pack.strings.at(stringId);
out << string;
}
void dumpFunctionName(const PackFromGlsl& pack, FunctionId functionId,
std::ostringstream& out) {
auto name = pack.functionNames.at(functionId);
auto indexParenthesis = name.find('(');
out << name.substr(0, indexParenthesis);
}
void dumpType(const PackFromGlsl& pack, TypeId typeId, std::ostringstream& out) {
ASSERT_PRECONDITION(pack.types.find(typeId) != pack.types.end(),
"Missing type definition");
auto& type = pack.types.at(typeId);
if (type.qualifiers) {
dumpString(pack, type.qualifiers.value(), out);
}
std::visit([&](auto&& name) {
using T = std::decay_t<decltype(name)>;
if constexpr (std::is_same_v<T, StringId>) {
dumpString(pack, name, out);
} else if constexpr (std::is_same_v<T, StructId>) {
ASSERT_PRECONDITION(pack.structs.find(name) != pack.structs.end(),
"Missing struct definition");
auto& strukt = pack.structs.at(name);
dumpString(pack, strukt.name, out);
} else {
static_assert(always_false_v<T>, "unreachable");
}
}, type.name);
for (const auto& arraySize : type.arraySizes) {
out << "[" << arraySize << "]";
}
}
void dumpBinaryExpressionOperator(
const PackFromGlsl& pack, const Function& function,
ExpressionOperator op, const std::vector<VariableOrExpressionId>& args,
const char* opString,
std::ostringstream& out) {
ASSERT_PRECONDITION(args.size() == 2,
"%s must be a binary operator", rValueOperatorToString(op));
dumpAnyVariableOrExpression(pack, function, args[0], /*parenthesize=*/true, out);
out << kSpace << opString << kSpace;
dumpAnyVariableOrExpression(pack, function, args[1], /*parenthesize=*/true, out);
}
template<>
void dumpExpressionOperandExpression<ExpressionOperator>(
const PackFromGlsl& pack, const Function& function,
const ExpressionOperator& op, const std::vector<VariableOrExpressionId>& args,
bool parenthesize, std::ostringstream& out) {
const char* lParen = parenthesize ? "(" : "";
const char* rParen = parenthesize ? ")" : "";
switch (op) {
// Unary
case ExpressionOperator::Negative:
ASSERT_PRECONDITION(args.size() == 1,
"Negative must be a unary operator");
out << "-";
dumpAnyVariableOrExpression(pack, function, args[0], /*parenthesize=*/true, out);
break;
case ExpressionOperator::LogicalNot:
ASSERT_PRECONDITION(args.size() == 1,
"LogicalNot must be a unary operator");
out << "!";
dumpAnyVariableOrExpression(pack, function, args[0], /*parenthesize=*/true, out);
break;
case ExpressionOperator::BitwiseNot:
ASSERT_PRECONDITION(args.size() == 1,
"BitwiseNot must be a unary operator");
out << "~";
dumpAnyVariableOrExpression(pack, function, args[0], /*parenthesize=*/true, out);
break;
case ExpressionOperator::PostIncrement:
ASSERT_PRECONDITION(args.size() == 1,
"PostIncrement must be a unary operator");
dumpAnyVariableOrExpression(pack, function, args[0], /*parenthesize=*/true, out);
out << "++";
break;
case ExpressionOperator::PostDecrement:
ASSERT_PRECONDITION(args.size() == 1,
"PostDecrement must be a unary operator");
dumpAnyVariableOrExpression(pack, function, args[0], /*parenthesize=*/true, out);
out << "--";
break;
case ExpressionOperator::PreIncrement:
ASSERT_PRECONDITION(args.size() == 1,
"PreIncrement must be a unary operator");
out << "++";
dumpAnyVariableOrExpression(pack, function, args[0], /*parenthesize=*/true, out);
break;
case ExpressionOperator::PreDecrement:
ASSERT_PRECONDITION(args.size() == 1,
"PreDecrement must be a unary operator");
out << "--";
dumpAnyVariableOrExpression(pack, function, args[0], /*parenthesize=*/true, out);
break;
case ExpressionOperator::ArrayLength:
ASSERT_PRECONDITION(args.size() == 1,
"ArrayLength must be a unary operator");
dumpAnyVariableOrExpression(pack, function, args[0], /*parenthesize=*/true, out);
out << ".length";
break;
// Binary
case ExpressionOperator::Add:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "+", out);
out << rParen;
break;
case ExpressionOperator::Sub:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "-", out);
out << rParen;
break;
case ExpressionOperator::Mul:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "*", out);
out << rParen;
break;
case ExpressionOperator::Div:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "/", out);
out << rParen;
break;
case ExpressionOperator::Mod:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "%", out);
out << rParen;
break;
case ExpressionOperator::RightShift:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, ">>", out);
out << rParen;
break;
case ExpressionOperator::LeftShift:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "<<", out);
out << rParen;
break;
case ExpressionOperator::And:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "&", out);
out << rParen;
break;
case ExpressionOperator::InclusiveOr:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "|", out);
out << rParen;
break;
case ExpressionOperator::ExclusiveOr:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "^", out);
out << rParen;
break;
case ExpressionOperator::Equal:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "==", out);
out << rParen;
break;
case ExpressionOperator::NotEqual:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "!=", out);
out << rParen;
break;
case ExpressionOperator::LessThan:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "<", out);
out << rParen;
break;
case ExpressionOperator::GreaterThan:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, ">", out);
out << rParen;
break;
case ExpressionOperator::LessThanEqual:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "<=", out);
out << rParen;
break;
case ExpressionOperator::GreaterThanEqual:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, ">=", out);
out << rParen;
break;
case ExpressionOperator::LogicalOr:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "||", out);
out << rParen;
break;
case ExpressionOperator::LogicalXor:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "^^", out);
out << rParen;
break;
case ExpressionOperator::LogicalAnd:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "&&", out);
out << rParen;
break;
case ExpressionOperator::Index:
ASSERT_PRECONDITION(args.size() == 2,
"%s must be a binary operator", rValueOperatorToString(op));
dumpAnyVariableOrExpression(pack, function, args[0], /*parenthesize=*/true, out);
out << "[";
dumpAnyVariableOrExpression(pack, function, args[1], /*parenthesize=*/true, out);
out << "]";
break;
case ExpressionOperator::Assign:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "=", out);
out << rParen;
break;
case ExpressionOperator::AddAssign:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "+=", out);
out << rParen;
break;
case ExpressionOperator::SubAssign:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "-=", out);
out << rParen;
break;
case ExpressionOperator::MulAssign:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "*=", out);
out << rParen;
break;
case ExpressionOperator::DivAssign:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "/=", out);
out << rParen;
break;
case ExpressionOperator::ModAssign:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "%=", out);
out << rParen;
break;
case ExpressionOperator::AndAssign:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "&=", out);
out << rParen;
break;
case ExpressionOperator::InclusiveOrAssign:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "|=", out);
out << rParen;
break;
case ExpressionOperator::ExclusiveOrAssign:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "^=", out);
out << rParen;
break;
case ExpressionOperator::LeftShiftAssign:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, "<<=", out);
out << rParen;
break;
case ExpressionOperator::RightShiftAssign:
out << lParen;
dumpBinaryExpressionOperator(pack, function, op, args, ">>=", out);
out << rParen;
break;
// Ternary
case ExpressionOperator::Ternary:
ASSERT_PRECONDITION(args.size() == 3,
"Ternary must be a ternary operator");
out << lParen << "(";
dumpAnyVariableOrExpression(pack, function, args[0], /*parenthesize=*/true, out);
out << ")" << kSpace << "?" << kSpace << "(";
dumpAnyVariableOrExpression(pack, function, args[1], /*parenthesize=*/true, out);
out << ")" << kSpace << ":" << kSpace << "(";
dumpAnyVariableOrExpression(pack, function, args[2], /*parenthesize=*/true, out);
out << ")" << rParen;
break;
// Variadic
case ExpressionOperator::Comma:
ASSERT_PRECONDITION(args.size() >= 2,
"Comma operator must have at least two arguments");
out << lParen;
dumpAnyVariableOrExpression(pack, function, args[0], /*parenthesize=*/false, out);
for (int i = 1; i < args.size(); i++) {
out << "," << kSpace;
dumpAnyVariableOrExpression(pack, function, args[i], /*parenthesize=*/false, out);
}
out << rParen;
break;
}
}
template <>
void dumpExpressionOperandExpression<FunctionId>(
const PackFromGlsl& pack, const Function& function,
const FunctionId& op, const std::vector<VariableOrExpressionId>& args,
bool parenthesize, std::ostringstream& out) {
dumpFunctionName(pack, op, out);
out << "(";
bool firstArg = true;
for (auto& arg : args) {
if (firstArg) {
firstArg = false;
} else {
out << "," << kSpace;
}
dumpAnyVariableOrExpression(pack, function, arg, /*parenthesize=*/false, out);
}
out << ")";
}
template <>
void dumpExpressionOperandExpression<StructId>(
const PackFromGlsl& pack, const Function& function,
const StructId& op, const std::vector<VariableOrExpressionId>& args,
bool parenthesize, std::ostringstream& out) {
ASSERT_PRECONDITION(pack.structs.find(op) != pack.structs.end(),
"Missing struct definition");
auto& strukt = pack.structs.at(op);
out << "(";
bool firstArg = true;
for (auto& arg : args) {
if (firstArg) {
firstArg = false;
} else {
out << "," << kSpace;
}
dumpAnyVariableOrExpression(pack, function, arg, /*parenthesize=*/false, out);
}
out << ")";
}
template<>
void dumpExpression<ExpressionOperandExpression>(
const PackFromGlsl& pack, const Function& function,
const ExpressionOperandExpression& value, bool parenthesize,
std::ostringstream& out) {
std::visit([&](auto&& op) {
dumpExpressionOperandExpression(pack, function, op, value.args, parenthesize, out);
}, value.op);
}
template<>
void dumpExpression<IndexStructExpression>(
const PackFromGlsl& pack, const Function& function,
const IndexStructExpression& value, bool parenthesize,
std::ostringstream& out) {
dumpAnyVariableOrExpression(pack, function, value.operand, /*parenthesize=*/true, out);
out << ".";
ASSERT_PRECONDITION(pack.structs.find(value.strukt) != pack.structs.end(),
"Missing struct definition");
auto& strukt = pack.structs.at(value.strukt);
ASSERT_PRECONDITION(value.index < strukt.members.size(),
"Struct member index out of bounds");
dumpString(pack, strukt.members[value.index].name, out);
}
template<>
void dumpExpression<VectorSwizzleExpression>(
const PackFromGlsl& pack, const Function& function,
const VectorSwizzleExpression& value, bool parenthesize,
std::ostringstream& out) {
static const char COMPONENTS[] = {'x', 'y', 'z', 'w'};
dumpAnyVariableOrExpression(pack, function, value.operand, /*parenthesize=*/true, out);
out << ".";
for (int i = 0; i < 4; i++) {
int component = (value.swizzle >> (i * 3)) & 0x7;
if (component == 0) {
break;
}
out << COMPONENTS[component - 1];
}
}
template<>
void dumpExpression<LiteralExpression>(
const PackFromGlsl& pack, const Function& function,
const LiteralExpression& value, bool parenthesize,
std::ostringstream& out) {
std::visit([&](auto&& value) {
out << value;
}, value.value);
}
template<>
void dumpVariableOrExpression<ExpressionId>(
const PackFromGlsl& pack, const Function& function, ExpressionId valueId,
bool parenthesize, std::ostringstream& out) {
if (*valueId == 0) {
out << "INVALID_EXPRESSION";
return;
}
ASSERT_PRECONDITION(pack.expressions.find(valueId) != pack.expressions.end(),
"Missing Expression");
std::visit([&](auto&& value) {
dumpExpression(pack, function, value, parenthesize, out);
}, pack.expressions.at(valueId));
}
template<>
void dumpVariableOrExpression<GlobalVariableId>(
const PackFromGlsl& pack, const Function& function, GlobalVariableId valueId,
bool parenthesize, std::ostringstream& out) {
if (*valueId == 0) {
out << "INVALID_GLOBAL_SYMBOL";
return;
}
ASSERT_PRECONDITION(pack.globalVariables.find(valueId) != pack.globalVariables.end(),
"Missing global symbol");
auto globalSymbol = pack.globalVariables.at(valueId);
dumpString(pack, globalSymbol.name, out);
}
template<>
void dumpVariableOrExpression<LocalVariableId>(
const PackFromGlsl& pack, const Function& function, LocalVariableId valueId,
bool parenthesize, std::ostringstream& out) {
if (*valueId == 0) {
out << "INVALID_LOCAL_SYMBOL";
return;
}
ASSERT_PRECONDITION(function.localVariables.find(valueId) != function.localVariables.end(),
"Missing local symbol");
auto& localSymbol = function.localVariables.at(valueId);
dumpString(pack, localSymbol.name, out);
}
template<>
void dumpStatement<ExpressionId>(
const PackFromGlsl& pack, const Function& function, StatementBlockId blockId,
const ExpressionId& statement, int depth,
std::ostringstream& out) {
indent(depth, out);
dumpAnyVariableOrExpression(pack, function, statement, /*parenthesize=*/false, out);
out << ";" << kNewline;
}
template<>
void dumpStatement<IfStatement>(
const PackFromGlsl& pack, const Function& function, StatementBlockId blockId,
const IfStatement& statement, int depth,
std::ostringstream& out) {
indent(depth, out);
out << "if" << kSpace << "(";
dumpAnyVariableOrExpression(pack, function, statement.condition, /*parenthesize=*/false, out);
out << ")" << kSpace << "{" << kNewline;
dumpBlock(pack, function, statement.thenBlock, depth + 1, out);
if (statement.elseBlock) {
indent(depth, out);
out << "}" << kSpace << "else" << kSpace << "{" << kNewline;
dumpBlock(pack, function, statement.elseBlock.value(), depth + 1, out);
}
indent(depth, out);
out << "}" << kNewline;
}
template<>
void dumpStatement<SwitchStatement>(
const PackFromGlsl& pack, const Function& function, StatementBlockId blockId,
const SwitchStatement& statement, int depth,
std::ostringstream& out) {
indent(depth, out);
out << "switch" << kSpace << "(";
dumpAnyVariableOrExpression(pack, function, statement.condition, /*parenthesize=*/false, out);
out << ")" << kSpace << "{" << kNewline;
dumpBlock(pack, function, statement.body, depth + 1, out);
indent(depth, out);
out << "}" << kNewline;
}
template<>
void dumpStatement<BranchStatement>(
const PackFromGlsl& pack, const Function& function, StatementBlockId blockId,
const BranchStatement& statement, int depth,
std::ostringstream& out) {
switch (statement.op) {
case BranchOperator::Discard:
indent(depth, out);
out << "discard";
break;
case BranchOperator::TerminateInvocation:
indent(depth, out);
out << "terminateInvocation";
break;
case BranchOperator::Demote:
indent(depth, out);
out << "demote";
break;
case BranchOperator::TerminateRayEXT:
indent(depth, out);
out << "terminateRayEXT";
break;
case BranchOperator::IgnoreIntersectionEXT:
indent(depth, out);
out << "terminateIntersectionEXT";
break;
case BranchOperator::Return:
indent(depth, out);
out << "return";
break;
case BranchOperator::Break:
indent(depth, out);
out << "break";
break;
case BranchOperator::Continue:
indent(depth, out);
out << "continue";
break;
case BranchOperator::Case:
indent(depth - 1, out);
out << "case";
break;
case BranchOperator::Default:
indent(depth - 1, out);
out << "default";
break;
}
if (statement.operand) {
out << " ";
dumpAnyVariableOrExpression(pack, function, statement.operand.value(),
/*parenthesize=*/false, out);
}
switch (statement.op) {
case BranchOperator::Case:
case BranchOperator::Default:
out << ":" << kNewline;
break;
default:
out << ";" << kNewline;
break;
}
}
template<>
void dumpStatement<LoopStatement>(
const PackFromGlsl& pack, const Function& function, StatementBlockId blockId,
const LoopStatement& statement, int depth,
std::ostringstream& out) {
if (statement.testFirst) {
if (statement.terminal) {
indent(depth, out);
out << "for" << kSpace << "(;" << kSpace;
dumpAnyVariableOrExpression(pack, function, statement.condition,
/*parenthesize=*/false, out);
out << ";" << kSpace;
dumpAnyVariableOrExpression(pack, function, statement.terminal.value(),
/*parenthesize=*/false, out);
} else {
indent(depth, out);
out << "while" << kSpace << "(";
dumpAnyVariableOrExpression(pack, function, statement.condition,
/*parenthesize=*/false, out);
}
out << ")" << kSpace << "{" << kNewline;
dumpBlock(pack, function, statement.body, depth + 1, out);
indent(depth, out);
out << "}" << kNewline;
} else {
indent(depth, out);
out << "do" << kSpace << "{" << kNewline;
dumpBlock(pack, function, statement.body, depth + 1, out);
indent(depth, out);
out << "}" << kSpace << "while" << kSpace << "(";
dumpAnyVariableOrExpression(pack, function, statement.condition, /*parenthesize=*/false, out);
out << ");" << kNewline;
}
}
void dumpAnyVariableOrExpression(
const PackFromGlsl& pack, const Function& function, VariableOrExpressionId valueId,
bool parenthesize, std::ostringstream& out) {
std::visit([&](auto&& variantValueId){
dumpVariableOrExpression(pack, function, variantValueId, parenthesize, out);
}, valueId);
}
void dumpBlock(
const PackFromGlsl& pack, const Function& function, StatementBlockId blockId,
int depth, std::ostringstream& out) {
ASSERT_PRECONDITION(pack.statementBlocks.find(blockId) != pack.statementBlocks.end(),
"Missing block definition");
for (auto statement : pack.statementBlocks.at(blockId)) {
std::visit([&](auto&& variantStatement){
dumpStatement(pack, function, blockId, variantStatement, depth, out);
}, statement);
}
}
void dumpSymbolDefinition(
const PackFromGlsl& pack, const Variable& symbol,
std::ostringstream& out) {
ASSERT_PRECONDITION(symbol.type.has_value(),
"Symbol definition must have type");
dumpType(pack, symbol.type.value(), out);
out << " "; // required space
dumpString(pack, symbol.name, out);
}
void dumpFunction(
const PackFromGlsl& pack, const FunctionId& functionId, bool dumpBody,
std::ostringstream& out) {
if (!dumpBody && pack.functions.find(functionId) == pack.functions.end()) {
// TODO: prune function prototypes with no actual definition.
return;
}
ASSERT_PRECONDITION(pack.functions.find(functionId) != pack.functions.end(),
"Missing function definition");
auto& function = pack.functions.at(functionId);
dumpType(pack, function.returnType, out);
out << " ";
dumpFunctionName(pack, function.name, out);
out << "(";
std::unordered_set<LocalVariableId> parameterSymbolIds;
bool firstParameter = true;
for (const auto& parameterId : function.parameters) {
if (firstParameter) {
firstParameter = false;
} else {
out << "," << kSpace;
}
parameterSymbolIds.insert(parameterId);
const auto& parameter = function.localVariables.at(parameterId);
dumpSymbolDefinition(pack, parameter, out);
}
out << ")";
if (dumpBody) {
out << kSpace << "{" << kNewline;
for (const auto& localSymbol : function.localVariables) {
if (parameterSymbolIds.find(localSymbol.first) == parameterSymbolIds.end()) {
out << kIndentAmount;
dumpSymbolDefinition(pack, localSymbol.second, out);
out << ";" << kNewline;
}
}
dumpBlock(pack, function, function.body, 1, out);
out << "}" << kNewline;
} else {
out << ";" << kNewline;
}
}
void dumpStruct(const PackFromGlsl& pack, StructId structId, std::ostringstream& out) {
ASSERT_PRECONDITION(pack.structs.find(structId) != pack.structs.end(),
"Missing struct definition");
auto& strukt = pack.structs.at(structId);
out << "struct ";
dumpString(pack, strukt.name, out);
out << kSpace << "{" << kNewline;
for (const auto& member : strukt.members) {
indent(1, out);
dumpType(pack, member.type, out);
out << " "; // non-optional
dumpString(pack, member.name, out);
out << ";" << kNewline;
}
out << "};" << kNewline;
}
void toGlsl(const PackFromGlsl& pack, std::ostringstream& out) {
const Function emptyFunction{};
for (auto structId : pack.structsInOrder) {
dumpStruct(pack, structId, out);
}
std::unordered_set<GlobalVariableId> globalSymbolIdsWithValues;
for (auto globalSymbolPair : pack.globalSymbolsInOrder) {
globalSymbolIdsWithValues.insert(globalSymbolPair.first);
}
for (auto globalSymbolPair : pack.globalVariables) {
if (globalSymbolIdsWithValues.find(globalSymbolPair.first)
== globalSymbolIdsWithValues.end()) {
const auto& globalSymbol = pack.globalVariables.at(globalSymbolPair.first);
if (globalSymbol.type) {
dumpSymbolDefinition(pack, globalSymbol, out);
out << ";" << kNewline;
}
}
}
for (auto globalSymbolPair : pack.globalSymbolsInOrder) {
const auto& globalSymbol = pack.globalVariables.at(globalSymbolPair.first);
dumpSymbolDefinition(pack, globalSymbol, out);
out << kSpace << "=" << kSpace;
dumpAnyVariableOrExpression(pack, emptyFunction, globalSymbolPair.second,
/*parenthesize=*/false, out);
out << ";" << kNewline;
}
for (auto functionId : pack.functionPrototypes) {
dumpFunction(pack, functionId, /*dumpBody=*/false, out);
}
for (auto functionId : pack.functionsInOrder) {
dumpFunction(pack, functionId, /*dumpBody=*/true, out);
}
}
} // namespace astrict
+35
View File
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <astrict/FromGlsl.h>
#include <gtest/gtest.h>
using namespace astrict;
TEST(Pack, Pack) {
std::string shaderCode(R"(
void material(inout MaterialInputs material) {
prepareMaterial(material);
material.baseColor = texture(materialParams_sampler, vec3(0.0, 0.0));
}
)");
// auto result = std::get<std::vector<uint8_t>>(compress(shaderCode));
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
@@ -20,13 +20,16 @@
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
#include <utils/CString.h>
#include <utils/FixedCapacityVector.h>
#include <initializer_list>
#include <unordered_map>
#include <string_view>
#include <vector>
#include <stddef.h>
#include <stdint.h>
namespace filament {
+1 -2
View File
@@ -81,7 +81,7 @@ include_directories(${CMAKE_BINARY_DIR})
add_library(${TARGET} STATIC ${HDRS} ${PRIVATE_HDRS} ${SRCS})
target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
set_target_properties(${TARGET} PROPERTIES FOLDER Libs)
target_link_libraries(${TARGET} shaders filabridge utils smol-v)
target_link_libraries(${TARGET} shaders filabridge utils smol-v astrict)
# We are being naughty and accessing private headers here
# For spirv-tools, we're just following glslang's example
@@ -157,4 +157,3 @@ target_include_directories(${TARGET} PRIVATE src)
target_link_libraries(${TARGET} filamat gtest)
set_target_properties(${TARGET} PROPERTIES FOLDER Tests)
+8
View File
@@ -43,6 +43,9 @@
#include <unordered_map>
#include <vector>
#include <astrict/FromGlsl.h>
#include <astrict/ToGlsl.h>
using namespace glslang;
using namespace spirv_cross;
using namespace spvtools;
@@ -372,6 +375,11 @@ bool GLSLPostProcessor::process(const std::string& inputShader, Config const& co
return false;
}
auto pack = astrict::fromGlsl(*tShader.getIntermediate());
std::ostringstream dump;
astrict::toGlsl(pack, dump);
slog.i << dump.str() << io::endl;
switch (mOptimization) {
case MaterialBuilder::Optimization::NONE:
if (internalConfig.spirvOutput) {
+14 -8
View File
@@ -17,13 +17,19 @@
#ifndef TNT_FILAMAT_FLATENNER_H
#define TNT_FILAMAT_FLATENNER_H
#include <utils/Panic.h>
#include <utility>
#include <utils/Log.h>
#include <utils/debug.h>
#include <utils/ostream.h>
#include <map>
#include <string_view>
#include <vector>
#include <assert.h>
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
using namespace utils;
@@ -97,7 +103,7 @@ public:
}
void writeString(const char* str) {
size_t len = strlen(str);
size_t const len = strlen(str);
if (mStart != nullptr) {
strcpy(reinterpret_cast<char*>(mCursor), str);
}
@@ -105,7 +111,7 @@ public:
}
void writeString(std::string_view str) {
size_t len = str.length();
size_t const len = str.length();
if (mStart != nullptr) {
memcpy(reinterpret_cast<char*>(mCursor), str.data(), len);
mCursor[len] = 0;
@@ -145,12 +151,12 @@ public:
}
uint32_t writeSize() {
assert(mSizePlaceholders.size() > 0);
assert(!mSizePlaceholders.empty());
uint8_t* dst = mSizePlaceholders.back();
mSizePlaceholders.pop_back();
// -4 to account for the 4 bytes we are about to write.
uint32_t size = static_cast<uint32_t>(mCursor - dst - 4);
uint32_t const size = static_cast<uint32_t>(mCursor - dst - 4);
if (mStart != nullptr) {
dst[0] = static_cast<uint8_t>( size & 0xff);
dst[1] = static_cast<uint8_t>((size >> 8) & 0xff);
@@ -177,12 +183,12 @@ public:
}
for(auto pair : mOffsetPlaceholders) {
size_t index = pair.first;
size_t const index = pair.first;
if (index != forIndex) {
continue;
}
uint8_t* dst = pair.second;
size_t offset = mCursor - mOffsetsBase;
size_t const offset = mCursor - mOffsetsBase;
if (offset > UINT32_MAX) {
slog.e << "Unable to write offset greater than UINT32_MAX." << io::endl;
exit(0);
@@ -206,7 +212,7 @@ public:
}
void writePlaceHoldValue(size_t v) {
assert(mValuePlaceholders.size() > 0);
assert(!mValuePlaceholders.empty());
if (v > UINT32_MAX) {
slog.e << "Unable to write value greater than UINT32_MAX." << io::endl;
+4 -1
View File
@@ -51,7 +51,10 @@ endif()
# ==================================================================================================
# Installation
# ==================================================================================================
install(TARGETS ${TARGET} ARCHIVE DESTINATION lib/${DIST_DIR})
# No need to install since we're combining this lib and the dependent libs into a combined lib
# install(TARGETS ${TARGET} ARCHIVE DESTINATION lib/${DIST_DIR})
install(DIRECTORY ${PUBLIC_HDR_DIR}/geometry DESTINATION include)
set(COMBINED_DEPS
@@ -21,6 +21,8 @@
#include <math/vec3.h>
#include <math/vec4.h>
#include <variant>
namespace filament {
namespace geometry {
@@ -106,16 +108,24 @@ public:
* - http://people.compute.dtu.dk/jerf/code/hairy/
*/
FRISVAD = 4,
/**
* Flat Shading
*
* **Requires**: `positions + indices` <br/>
* **Note**: Will remesh
*/
FLAT_SHADING = 5
};
/**
* This enum specifies the auxiliary attributes of each vertex that can be provided as input.
* These attributes do not affect the computation of the tangent space, but they will be
* properly mapped when a remeshing is carried out.
*/
enum class AuxAttribute : uint8_t {
UV1 = 0x0,
COLORS = 0x1,
JOINTS = 0x2,
WEIGHTS = 0x3,
};
using InData = std::variant<filament::math::float2 const*, filament::math::float3 const*,
filament::math::float4 const*, filament::math::ushort3 const*,
filament::math::ushort4 const*>;
/**
* Use this class to provide input to the TangentSpaceMesh computation. **Important**:
* Computation of the tangent space is intended to be synchronous (working on the same thread).
@@ -170,6 +180,16 @@ public:
*/
Builder& uvs(filament::math::float2 const* uvs, size_t stride = 0) noexcept;
/**
* Sets "auxiliary" attributes that will be properly mapped when remeshed.
*
* @param attribute The attribute of the data to be stored
* @param data The data to be store
* @param stride The stride for iterating through `attribute`
* @return Builder
*/
Builder& aux(AuxAttribute attribute, InData data, size_t stride = 0) noexcept;
/**
* @param positions The input positions
* @param stride The stride for iterating through `positions`
@@ -177,10 +197,30 @@ public:
*/
Builder& positions(filament::math::float3 const* positions, size_t stride = 0) noexcept;
/**
* @param triangleCount The input number of triangles
* @return Builder
*/
Builder& triangleCount(size_t triangleCount) noexcept;
/**
* @param triangles The triangles in 32-bit indices
* @return Builder
*/
Builder& triangles(filament::math::uint3 const* triangles) noexcept;
/**
* @param triangles The triangles in 16-bit indices
* @return Builder
*/
Builder& triangles(filament::math::ushort3 const* triangles) noexcept;
/**
* The Client can provide an algorithm hint to produce the tangents.
*
* @param algorithm The algorithm hint.
* @return Builder
*/
Builder& algorithm(Algorithm algorithm) noexcept;
/**
@@ -199,7 +239,7 @@ public:
};
/**
* Destory the mesh object
* Destroy the mesh object
* @param mesh A pointer to a TangentSpaceMesh ready to be destroyed
*/
static void destroy(TangentSpaceMesh* mesh) noexcept;
@@ -284,6 +324,24 @@ public:
*/
void getQuats(filament::math::quath* out, size_t stride = 0) const noexcept;
/**
* Get output auxiliary attributes.
* Assumes the `out` param is at least of getVertexCount() length (while accounting for
* `stride`).
*
* @param out Client-allocated array that will be used for copying out attribute as T
* @param stride Stride for iterating through `out`
*/
template<typename T>
using is_supported_aux_t =
typename std::enable_if<std::is_same<filament::math::float2, T>::value ||
std::is_same<filament::math::float3, T>::value ||
std::is_same<filament::math::float4, T>::value ||
std::is_same<filament::math::ushort3, T>::value ||
std::is_same<filament::math::ushort4, T>::value>::type;
template<typename T, typename = is_supported_aux_t<T>>
void getAux(AuxAttribute attribute, T* out, size_t stride = 0) const noexcept;
/**
* Get number of output triangles.
* The number of output triangles is the same as the number of input triangles. However, when a
@@ -315,9 +373,9 @@ public:
void getTriangles(filament::math::ushort3* out) const;
/**
* @return The algorithm used to compute the output mesh.
* @return Whether the TBN algorithm remeshed the input.
*/
Algorithm getAlgorithm() const noexcept;
bool remeshed() const noexcept;
private:
~TangentSpaceMesh() noexcept;
+55 -19
View File
@@ -75,27 +75,61 @@ void MikktspaceImpl::setTSpaceBasic(SMikkTSpaceContext const* context, float con
float3 const pos = *pointerAdd(wrapper->mPositions, vertInd, wrapper->mPositionStride);
float3 const n = normalize(*pointerAdd(wrapper->mNormals, vertInd, wrapper->mNormalStride));
float2 const uv = *pointerAdd(wrapper->mUVs, vertInd, wrapper->mUVStride);
float3 const t{fvTangent[0], fvTangent[1], fvTangent[2]};
float3 const t { fvTangent[0], fvTangent[1], fvTangent[2] };
float3 const b = fSign * normalize(cross(n, t));
// TODO: packTangentFrame actually changes the orientation of b.
quatf const quat = mat3f::packTangentFrame({t, b, n}, sizeof(int32_t));
wrapper->mOutVertices.push_back({pos, uv, quat});
auto output = wrapper->mOutputData;
auto const& EMPTY_ELEMENT = wrapper->EMPTY_ELEMENT;
size_t const outputCurSize = output.size();
// Prepare for the next element
output.insert(output.end(), EMPTY_ELEMENT.begin(), EMPTY_ELEMENT.end());
uint8_t* cursor = output.data() + outputCurSize;
*((float3*) (cursor)) = pos;
*((float2*) (cursor + 12)) = uv;
*((quatf*) (cursor + 20)) = quat;
cursor += 36;
for (auto [attribArray, attribStride, attribSize]: wrapper->mInputAttribArrays) {
uint8_t const* input = pointerAdd(attribArray, vertInd, attribStride);
std::memcpy(cursor, input, attribSize);
cursor += attribSize;
}
}
MikktspaceImpl::MikktspaceImpl(const TangentSpaceMeshInput* input) noexcept
: mFaceCount((int) input->triangleCount),
mPositions(input->positions),
mPositionStride(input->positionStride ? input->positionStride : sizeof(float3)),
mNormals(input->normals),
mNormalStride(input->normalStride ? input->normalStride : sizeof(float3)),
mUVs(input->uvs),
mUVStride(input->uvStride ? input->uvStride : sizeof(float2)),
mPositions(input->positions()),
mPositionStride(input->positionsStride()),
mNormals(input->normals()),
mNormalStride(input->normalsStride()),
mUVs(input->uvs()),
mUVStride(input->uvsStride()),
mIsTriangle16(input->triangles16),
mTriangles(
input->triangles16 ? (uint8_t*) input->triangles16 : (uint8_t*) input->triangles32) {
mOutVertices.reserve(mFaceCount * 3);
input->triangles16 ? (uint8_t*) input->triangles16 : (uint8_t*) input->triangles32),
mOutputElementSize(BASE_OUTPUT_SIZE) {
// We don't know how many attributes there are so we have to create an ordering of the
// output components. The first three components are
// - float3 positions
// - float2 uv
// - quatf tangent
for (auto attrib: input->getAuxAttributes()) {
size_t const attribSize =input->attributeSize(attrib);
mOutputElementSize += attribSize;
mInputAttribArrays.push_back({input->raw(attrib), input->stride(attrib), attribSize});
}
mOutputData.reserve(mFaceCount * 3 * mOutputElementSize);
// We will insert 0s to signify a new element being added to the output.
EMPTY_ELEMENT = std::vector<uint8_t>(mOutputElementSize);
}
MikktspaceImpl* MikktspaceImpl::getThis(SMikkTSpaceContext const* context) noexcept {
@@ -120,20 +154,22 @@ void MikktspaceImpl::run(TangentSpaceMeshOutput* output) noexcept {
SMikkTSpaceContext context{.m_pInterface = &interface, .m_pUserData = this};
genTangSpaceDefault(&context);
std::vector<unsigned int> remap(mOutVertices.size());
size_t vertexCount = meshopt_generateVertexRemap(remap.data(), NULL, mOutVertices.size(),
mOutVertices.data(), mOutVertices.size(), sizeof(IOVertex));
size_t oVertexCount = mOutputData.size() / mOutputElementSize;
std::vector<unsigned int> remap(oVertexCount);
size_t vertexCount = meshopt_generateVertexRemap(remap.data(), NULL, remap.size(),
mOutputData.data(), oVertexCount, mOutputElementSize);
std::vector<IOVertex> newVertices(vertexCount);
meshopt_remapVertexBuffer((void*) newVertices.data(), mOutVertices.data(), mOutVertices.size(),
sizeof(IOVertex), remap.data());
meshopt_remapVertexBuffer((void*) newVertices.data(), mOutputData.data(), oVertexCount,
mOutputElementSize, remap.data());
uint3* triangles32 = output->triangles32.allocate(mFaceCount);
meshopt_remapIndexBuffer((uint32_t*) triangles32, NULL, mOutVertices.size(), remap.data());
meshopt_remapIndexBuffer((uint32_t*) triangles32, NULL, remap.size(), remap.data());
float3* outPositions = output->positions.allocate(vertexCount);
float2* outUVs = output->uvs.allocate(vertexCount);
quatf* outQuats = output->tangentSpace.allocate(vertexCount);
float3* outPositions = output->positions().allocate(vertexCount);
float2* outUVs = output->uvs().allocate(vertexCount);
quatf* outQuats = output->tspace().allocate(vertexCount);
for (size_t i = 0; i < vertexCount; ++i) {
outPositions[i] = newVertices[i].position;

Some files were not shown because too many files have changed in this diff Show More