Compare commits

..
20 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
75 changed files with 4697 additions and 546 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))))
+1 -1
View File
@@ -10,7 +10,7 @@ on:
jobs:
build-android:
name: build-android
runs-on: macos-14
runs-on: macos-latest
steps:
- uses: actions/checkout@v3.3.0
+1 -1
View File
@@ -13,7 +13,7 @@ on:
jobs:
cocoapods-deploy:
name: cocoapods-deploy
runs-on: macos-14
runs-on: macos-latest
steps:
- name: Check out iOS/CocoaPods directory
uses: Bhacaz/checkout-files@49fc3050859046bf4f4873678d46099985640e89
+1 -1
View File
@@ -10,7 +10,7 @@ on:
jobs:
build-ios:
name: build-ios
runs-on: macos-14
runs-on: macos-latest
steps:
- uses: actions/checkout@v3.3.0
+1 -1
View File
@@ -10,7 +10,7 @@ on:
jobs:
build-mac:
name: build-mac
runs-on: macos-14
runs-on: macos-latest
steps:
- uses: actions/checkout@v3.3.0
+1 -1
View File
@@ -11,7 +11,7 @@ on:
jobs:
npm-deploy:
name: npm-deploy
runs-on: macos-14
runs-on: macos-latest
steps:
- uses: actions/checkout@v3.3.0
with:
+4 -4
View File
@@ -15,7 +15,7 @@ jobs:
strategy:
matrix:
os: [macos-14, ubuntu-22.04]
os: [macos-latest, ubuntu-22.04]
steps:
- uses: actions/checkout@v3.3.0
@@ -40,7 +40,7 @@ jobs:
build-android:
name: build-android
runs-on: macos-14
runs-on: macos-latest
steps:
- uses: actions/checkout@v3.3.0
@@ -54,7 +54,7 @@ jobs:
build-ios:
name: build-iOS
runs-on: macos-14
runs-on: macos-latest
steps:
- uses: actions/checkout@v3.3.0
@@ -67,7 +67,7 @@ jobs:
build-web:
name: build-web
runs-on: macos-14
runs-on: macos-latest
steps:
- uses: actions/checkout@v3.3.0
+5 -5
View File
@@ -31,7 +31,7 @@ jobs:
strategy:
matrix:
os: [macos-14, ubuntu-22.04]
os: [macos-latest, ubuntu-22.04]
steps:
- name: Decide Git ref
@@ -65,7 +65,7 @@ jobs:
build-web:
name: build-web
runs-on: macos-14
runs-on: macos-latest
if: github.event_name == 'release' || github.event.inputs.platform == 'web'
steps:
@@ -98,7 +98,7 @@ jobs:
build-android:
name: build-android
runs-on: macos-14
runs-on: macos-latest
if: github.event_name == 'release' || github.event.inputs.platform == 'android'
steps:
@@ -129,7 +129,7 @@ jobs:
- name: Sign sample-gltf-viewer
run: |
echo "${APK_KEYSTORE_BASE64}" > filament.jks.base64
base64 --decode -i filament.jks.base64 > filament.jks
base64 --decode filament.jks.base64 > filament.jks
BUILD_TOOLS_VERSION=$(ls ${ANDROID_HOME}/build-tools | sort -V | tail -n 1)
APKSIGNER=${ANDROID_HOME}/build-tools/${BUILD_TOOLS_VERSION}/apksigner
IN_FILE="out/sample-gltf-viewer-release.apk"
@@ -152,7 +152,7 @@ jobs:
build-ios:
name: build-ios
runs-on: macos-14
runs-on: macos-latest
if: github.event_name == 'release' || github.event.inputs.platform == 'ios'
steps:
+1 -1
View File
@@ -10,7 +10,7 @@ on:
jobs:
build-web:
name: build-web
runs-on: macos-14
runs-on: macos-latest
steps:
- uses: actions/checkout@v3.3.0
+2 -1
View File
@@ -706,7 +706,7 @@ function(get_resgen_vars ARCHIVE_DIR ARCHIVE_NAME)
set(RESGEN_OUTPUTS "${OUTPUTS}" PARENT_SCOPE)
set(RESGEN_FLAGS -qx ${ARCHIVE_DIR} -p ${ARCHIVE_NAME} PARENT_SCOPE)
set(RESGEN_SOURCE "${ARCHIVE_DIR}/${ARCHIVE_NAME}${ASM_SUFFIX}.S" PARENT_SCOPE)
set(RESGEN_SOURCE_FLAGS "-I'${ARCHIVE_DIR}' ${ASM_ARCH_FLAG}" PARENT_SCOPE)
set(RESGEN_SOURCE_FLAGS "-I${ARCHIVE_DIR} ${ASM_ARCH_FLAG}" PARENT_SCOPE)
endif()
endfunction()
@@ -757,6 +757,7 @@ if (FILAMENT_BUILD_FILAMAT OR IS_HOST_PLATFORM)
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.3'
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.3'
pod 'Filament', '~> 1.50.0'
```
### Snapshots
-6
View File
@@ -7,12 +7,6 @@ A new header is inserted each time a *tag* is created.
Instead, if you are authoring a PR for the main branch, add your release note to
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
## v1.50.3
## v1.50.2
## v1.50.1
- Metal: fix some shader artifacts by disabling fast math optimizations.
@@ -484,8 +484,7 @@ extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBu
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBuilderConfig(JNIEnv*,
jclass, jlong nativeBuilder, jlong commandBufferSizeMB, jlong perRenderPassArenaSizeMB,
jlong driverHandleArenaSizeMB, jlong minCommandBufferSizeMB, jlong perFrameCommandsSizeMB,
jlong jobSystemThreadCount, jlong stereoscopicEyeCount,
jlong resourceAllocatorCacheSizeMB, jlong resourceAllocatorCacheMaxAge) {
jlong jobSystemThreadCount, jlong stereoscopicEyeCount) {
Engine::Builder* builder = (Engine::Builder*) nativeBuilder;
Engine::Config config = {
.commandBufferSizeMB = (uint32_t) commandBufferSizeMB,
@@ -495,8 +494,6 @@ extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBu
.perFrameCommandsSizeMB = (uint32_t) perFrameCommandsSizeMB,
.jobSystemThreadCount = (uint32_t) jobSystemThreadCount,
.stereoscopicEyeCount = (uint8_t) stereoscopicEyeCount,
.resourceAllocatorCacheSizeMB = (uint32_t) resourceAllocatorCacheSizeMB,
.resourceAllocatorCacheMaxAge = (uint8_t) resourceAllocatorCacheMaxAge,
};
builder->config(&config);
}
@@ -211,8 +211,7 @@ public class Engine {
nSetBuilderConfig(mNativeBuilder, config.commandBufferSizeMB,
config.perRenderPassArenaSizeMB, config.driverHandleArenaSizeMB,
config.minCommandBufferSizeMB, config.perFrameCommandsSizeMB,
config.jobSystemThreadCount, config.stereoscopicEyeCount,
config.resourceAllocatorCacheSizeMB, config.resourceAllocatorCacheMaxAge);
config.jobSystemThreadCount, config.stereoscopicEyeCount);
return this;
}
@@ -357,18 +356,6 @@ public class Engine {
* @see Engine#getMaxStereoscopicEyes
*/
public long stereoscopicEyeCount = 2;
/*
* Size in MiB of the frame graph texture cache. This should be adjusted based on the
* size of used render targets (typically the screen).
*/
public long resourceAllocatorCacheSizeMB = 64;
/*
* This value determines for how many frames are texture entries kept in the cache.
* The default value of 30 corresponds to about half a second at 60 fps.
*/
public long resourceAllocatorCacheMaxAge = 30;
}
private Engine(long nativeEngine, Config config) {
@@ -1240,8 +1227,7 @@ public class Engine {
private static native void nSetBuilderConfig(long nativeBuilder, long commandBufferSizeMB,
long perRenderPassArenaSizeMB, long driverHandleArenaSizeMB,
long minCommandBufferSizeMB, long perFrameCommandsSizeMB, long jobSystemThreadCount,
long stereoscopicEyeCount,
long resourceAllocatorCacheSizeMB, long resourceAllocatorCacheMaxAge);
long stereoscopicEyeCount);
private static native void nSetBuilderFeatureLevel(long nativeBuilder, int ordinal);
private static native void nSetBuilderSharedContext(long nativeBuilder, long sharedContext);
private static native long nBuilderBuild(long nativeBuilder);
+1 -1
View File
@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.50.3
VERSION_NAME=1.50.0
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
+1 -7
View File
@@ -125,13 +125,7 @@ if [[ "${has_universal}" == "true" ]]; then
arch_output="${OUTPUT_PATH%.a}_${arch}.a"
arch_outputs+=("$arch_output")
archives=()
while IFS= read -r -d $'\0'; do
archives+=("$REPLY")
done < <(find "$(pwd)/${archs_temp_dir}/${arch}" -iname '*.a' -print0)
combine_static_libs "$arch_output" "$archives"
combine_static_libs "$arch_output" $(find "$(pwd)/${archs_temp_dir}/${arch}" -iname '*.a')
done
# Finally, combine the single-architecture archives into a universal binary.
+5 -9
View File
@@ -84,7 +84,7 @@ public:
*
* @return nullptr on failure, or a pointer to the newly created driver.
*/
virtual backend::Driver* UTILS_NULLABLE createDriver(void* UTILS_NULLABLE sharedContext,
virtual backend::Driver* createDriver(void* sharedContext,
const DriverConfig& driverConfig) noexcept = 0;
/**
@@ -102,8 +102,7 @@ public:
* cache.
*/
using InsertBlobFunc = utils::Invocable<
void(const void* UTILS_NONNULL key, size_t keySize,
const void* UTILS_NONNULL value, size_t valueSize)>;
void(const void* key, size_t keySize, const void* value, size_t valueSize)>;
/*
* RetrieveBlobFunc is an Invocable to an application-provided function that a
@@ -111,8 +110,7 @@ public:
* cache.
*/
using RetrieveBlobFunc = utils::Invocable<
size_t(const void* UTILS_NONNULL key, size_t keySize,
void* UTILS_NONNULL value, size_t valueSize)>;
size_t(const void* key, size_t keySize, void* value, size_t valueSize)>;
/**
* Sets the callback functions that the backend can use to interact with caching functionality
@@ -165,8 +163,7 @@ public:
* @param value pointer to the beginning of the value data that is to be inserted
* @param valueSize specifies the size in byte of the data pointed to by <value>
*/
void insertBlob(const void* UTILS_NONNULL key, size_t keySize,
const void* UTILS_NONNULL value, size_t valueSize);
void insertBlob(const void* key, size_t keySize, const void* value, size_t valueSize);
/**
* To retrieve the binary value associated with a given key from the cache, a
@@ -185,8 +182,7 @@ public:
* @return If the cache contains a value associated with the given key then the
* size of that binary value in bytes is returned. Otherwise 0 is returned.
*/
size_t retrieveBlob(const void* UTILS_NONNULL key, size_t keySize,
void* UTILS_NONNULL value, size_t valueSize);
size_t retrieveBlob(const void* key, size_t keySize, void* value, size_t valueSize);
private:
InsertBlobFunc mInsertBlob;
@@ -21,8 +21,6 @@
#include <backend/DriverEnums.h>
#include <backend/Platform.h>
#include <utils/compiler.h>
#include <stdint.h>
namespace filament::backend {
@@ -43,8 +41,8 @@ protected:
* Derived classes can use this to instantiate the default OpenGLDriver backend.
* This is typically called from your implementation of createDriver()
*/
static Driver* UTILS_NULLABLE createDefaultDriver(OpenGLPlatform* UTILS_NONNULL platform,
void* UTILS_NULLABLE sharedContext, const DriverConfig& driverConfig);
static Driver* createDefaultDriver(OpenGLPlatform* platform,
void* sharedContext, const DriverConfig& driverConfig);
~OpenGLPlatform() noexcept override;
@@ -71,8 +69,7 @@ public:
* @return The driver's SwapChain object.
*
*/
virtual SwapChain* UTILS_NONNULL createSwapChain(
void* UTILS_NULLABLE nativeWindow, uint64_t flags) noexcept = 0;
virtual SwapChain* createSwapChain(void* nativeWindow, uint64_t flags) noexcept = 0;
/**
* Return whether createSwapChain supports the SWAP_CHAIN_CONFIG_SRGB_COLORSPACE flag.
@@ -93,14 +90,13 @@ public:
* TODO: we need a more generic way of passing construction parameters
* A void* might be enough.
*/
virtual SwapChain* UTILS_NULLABLE createSwapChain(
uint32_t width, uint32_t height, uint64_t flags) noexcept = 0;
virtual SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept = 0;
/**
* Called by the driver to destroys the SwapChain
* @param swapChain SwapChain to be destroyed.
*/
virtual void destroySwapChain(SwapChain* UTILS_NONNULL swapChain) noexcept = 0;
virtual void destroySwapChain(SwapChain* swapChain) noexcept = 0;
/**
* Returns the set of buffers that must be preserved up to the call to commit().
@@ -113,7 +109,7 @@ public:
* @return buffer that must be preserved
* @see commit()
*/
virtual TargetBufferFlags getPreservedFlags(SwapChain* UTILS_NONNULL swapChain) noexcept;
virtual TargetBufferFlags getPreservedFlags(SwapChain* swapChain) noexcept;
/**
* Called by the driver to establish the default FBO. The default implementation returns 0.
@@ -127,16 +123,14 @@ public:
* @param drawSwapChain SwapChain to draw to. It must be bound to the default FBO.
* @param readSwapChain SwapChain to read from (for operation like `glBlitFramebuffer`)
*/
virtual void makeCurrent(
SwapChain* UTILS_NONNULL drawSwapChain,
SwapChain* UTILS_NONNULL readSwapChain) noexcept = 0;
virtual void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept = 0;
/**
* Called by the driver once the current frame finishes drawing. Typically, this should present
* the drawSwapChain. This is for example where `eglMakeCurrent()` would be called.
* @param swapChain the SwapChain to present.
*/
virtual void commit(SwapChain* UTILS_NONNULL swapChain) noexcept = 0;
virtual void commit(SwapChain* swapChain) noexcept = 0;
/**
* Set the time the next committed buffer should be presented to the user at.
@@ -161,14 +155,14 @@ public:
*
* @return A Fence object. The default implementation returns nullptr.
*/
virtual Fence* UTILS_NULLABLE createFence() noexcept;
virtual Fence* createFence() noexcept;
/**
* Destroys a Fence object. The default implementation does nothing.
*
* @param fence Fence to destroy.
*/
virtual void destroyFence(Fence* UTILS_NONNULL fence) noexcept;
virtual void destroyFence(Fence* fence) noexcept;
/**
* Waits on a Fence.
@@ -178,7 +172,7 @@ public:
* @return Whether the fence signaled or timed out. See backend::FenceStatus.
* The default implementation always return backend::FenceStatus::ERROR.
*/
virtual backend::FenceStatus waitFence(Fence* UTILS_NONNULL fence, uint64_t timeout) noexcept;
virtual backend::FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept;
// --------------------------------------------------------------------------------------------
@@ -192,13 +186,13 @@ public:
* @param nativeStream The native stream, this parameter depends on the concrete implementation.
* @return A new Stream object.
*/
virtual Stream* UTILS_NULLABLE createStream(void* UTILS_NULLABLE nativeStream) noexcept;
virtual Stream* createStream(void* nativeStream) noexcept;
/**
* Destroys a Stream.
* @param stream Stream to destroy.
*/
virtual void destroyStream(Stream* UTILS_NONNULL stream) noexcept;
virtual void destroyStream(Stream* stream) noexcept;
/**
* The specified stream takes ownership of the texture (tname) object
@@ -208,21 +202,20 @@ public:
* @param stream Stream to take ownership of the texture
* @param tname GL texture id to "bind" to the Stream.
*/
virtual void attach(Stream* UTILS_NONNULL stream, intptr_t tname) noexcept;
virtual void attach(Stream* stream, intptr_t tname) noexcept;
/**
* Destroys the texture associated to the stream
* @param stream Stream to detach from its texture
*/
virtual void detach(Stream* UTILS_NONNULL stream) noexcept;
virtual void detach(Stream* stream) noexcept;
/**
* Updates the content of the texture attached to the stream.
* @param stream Stream to update
* @param timestamp Output parameter: Timestamp of the image bound to the texture.
*/
virtual void updateTexImage(Stream* UTILS_NONNULL stream,
int64_t* UTILS_NONNULL timestamp) noexcept;
virtual void updateTexImage(Stream* stream, int64_t* timestamp) noexcept;
// --------------------------------------------------------------------------------------------
@@ -235,13 +228,13 @@ public:
* implementation could just return { 0, GL_TEXTURE_2D } at this point. The actual
* values can be delayed until setExternalImage.
*/
virtual ExternalTexture* UTILS_NULLABLE createExternalImageTexture() noexcept;
virtual ExternalTexture *createExternalImageTexture() noexcept;
/**
* Destroys an external texture handle and associated data.
* @param texture a pointer to the handle to destroy.
*/
virtual void destroyExternalImage(ExternalTexture* UTILS_NONNULL texture) noexcept;
virtual void destroyExternalImage(ExternalTexture* texture) noexcept;
// called on the application thread to allow Filament to take ownership of the image
@@ -254,7 +247,7 @@ public:
* @param externalImage A token representing the platform's external image.
* @see destroyExternalImage
*/
virtual void retainExternalImage(void* UTILS_NONNULL externalImage) noexcept;
virtual void retainExternalImage(void* externalImage) noexcept;
/**
* Called to bind the platform-specific externalImage to an ExternalTexture.
@@ -268,8 +261,7 @@ public:
* @param texture an in/out pointer to ExternalTexture, id and target can be updated if necessary.
* @return true on success, false on error.
*/
virtual bool setExternalImage(void* UTILS_NONNULL externalImage,
ExternalTexture* UTILS_NONNULL texture) noexcept;
virtual bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept;
/**
* The method allows platforms to convert a user-supplied external image object into a new type
+33 -51
View File
@@ -245,53 +245,30 @@ void MetalSwapChain::present() {
}
}
#ifndef FILAMENT_RELEASE_PRESENT_DRAWABLE_MAIN_THREAD
#define FILAMENT_RELEASE_PRESENT_DRAWABLE_MAIN_THREAD 1
#endif
class PresentDrawableData {
public:
PresentDrawableData() = delete;
PresentDrawableData(const PresentDrawableData&) = delete;
PresentDrawableData& operator=(const PresentDrawableData&) = delete;
static PresentDrawableData* create(id<CAMetalDrawable> drawable, MetalDriver* driver) {
assert_invariant(driver);
return new PresentDrawableData(drawable, driver);
}
static void maybePresentAndDestroyAsync(PresentDrawableData* that, bool shouldPresent) {
if (shouldPresent) {
[that->mDrawable present];
}
#if FILAMENT_RELEASE_PRESENT_DRAWABLE_MAIN_THREAD == 1
// mDrawable is acquired on the driver thread. Typically, we would release this object on
// the same thread, but after receiving consistent crash reports from within
// [CAMetalDrawable dealloc], we suspect this object requires releasing on the main thread.
dispatch_async(dispatch_get_main_queue(), ^{ cleanupAndDestroy(that); });
#else
that->mDriver->runAtNextTick([that]() { cleanupAndDestroy(that); });
#endif
}
private:
PresentDrawableData(id<CAMetalDrawable> drawable, MetalDriver* driver)
: mDrawable(drawable), mDriver(driver) {}
static void cleanupAndDestroy(PresentDrawableData *that) {
that->mDrawable = nil;
that->mDriver = nullptr;
delete that;
}
id<CAMetalDrawable> mDrawable;
MetalDriver* mDriver = nullptr;
struct PresentDrawableData {
void* drawable = nullptr;
MetalDriver* driver = nullptr;
};
void presentDrawable(bool presentFrame, void* user) {
auto* presentDrawableData = static_cast<PresentDrawableData*>(user);
PresentDrawableData::maybePresentAndDestroyAsync(presentDrawableData, presentFrame);
// CFBridgingRelease here is used to balance the CFBridgingRetain inside acquireDrawable.
id<CAMetalDrawable> drawable =
(id<CAMetalDrawable>)CFBridgingRelease(presentDrawableData->drawable);
if (presentFrame) {
[drawable present];
}
// Schedule the drawable destruction on the driver thread.
void* voidDrawable = (void*) CFBridgingRetain(drawable);
MetalDriver* driver = presentDrawableData->driver;
driver->runAtNextTick([voidDrawable]() {
// The drawable is released here.
CFBridgingRelease(voidDrawable);
});
delete presentDrawableData;
}
void MetalSwapChain::scheduleFrameScheduledCallback() {
@@ -300,16 +277,21 @@ void MetalSwapChain::scheduleFrameScheduledCallback() {
}
assert_invariant(drawable);
// Destroy this by calling maybePresentAndDestroyAsync() later.
auto* presentData = PresentDrawableData::create(drawable, context.driver);
FrameScheduledCallback userCallback = frameScheduledCallback;
FrameScheduledCallback callback = frameScheduledCallback;
// This block strongly captures drawable to keep it alive until the handler executes.
// We cannot simply reference this->drawable inside the block because the block would then only
// capture the _this_ pointer (MetalSwapChain*) instead of the drawable.
id<CAMetalDrawable> d = drawable;
void* userData = frameScheduledUserData;
MetalDriver* driver = context.driver;
[getPendingCommandBuffer(&context) addScheduledHandler:^(id<MTLCommandBuffer> cb) {
PresentCallable callable(presentDrawable, static_cast<void*>(presentData));
userCallback(callable, userData);
// CFBridgingRetain is used here to give the drawable a +1 retain count before
// casting it to a void*.
auto* presentDrawableData = new PresentDrawableData;
presentDrawableData->drawable = (void*) CFBridgingRetain(d);
presentDrawableData->driver = driver;
PresentCallable callable(presentDrawable, (void*) presentDrawableData);
callback(callable, userData);
}];
}
+3 -2
View File
@@ -84,7 +84,8 @@ public:
*
* @param engine Reference to the filament::Engine to associate this BufferObject with.
*
* @return pointer to the newly created object
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
*
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
* memory or other resources.
@@ -92,7 +93,7 @@ public:
*
* @see IndexBuffer::setBuffer
*/
BufferObject* UTILS_NONNULL build(Engine& engine);
BufferObject* build(Engine& engine);
private:
friend class FBufferObject;
};
+1 -1
View File
@@ -306,7 +306,7 @@ public:
* @see setCustomProjection
* @see Engine::Config::stereoscopicEyeCount
*/
void setCustomEyeProjection(math::mat4 const* UTILS_NONNULL projection, size_t count,
void setCustomEyeProjection(math::mat4 const* projection, size_t count,
math::mat4 const& projectionForCulling, double near, double far);
/** Sets an additional matrix that scales the projection matrix.
+4 -3
View File
@@ -203,7 +203,7 @@ public:
*
* @return This Builder, for chaining calls
*/
Builder& toneMapper(ToneMapper const* UTILS_NULLABLE toneMapper) noexcept;
Builder& toneMapper(const ToneMapper* toneMapper) noexcept;
/**
* Selects the tone mapping operator to apply to the HDR color buffer as the last
@@ -473,9 +473,10 @@ public:
*
* @param engine Reference to the filament::Engine to associate this ColorGrading with.
*
* @return pointer to the newly created object.
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
*/
ColorGrading* UTILS_NONNULL build(Engine& engine);
ColorGrading* build(Engine& engine);
private:
friend class FColorGrading;
+36 -23
View File
@@ -39,12 +39,27 @@ namespace filament {
class UTILS_PUBLIC DebugRegistry : public FilamentAPI {
public:
/**
* Type of a property
*/
enum Type {
BOOL, INT, FLOAT, FLOAT2, FLOAT3, FLOAT4
};
/**
* Information about a property
*/
struct Property {
const char* name; //!< property name
Type type; //!< property type
};
/**
* Queries whether a property exists
* @param name The name of the property to query
* @return true if the property exists, false otherwise
*/
bool hasProperty(const char* UTILS_NONNULL name) const noexcept;
bool hasProperty(const char* name) const noexcept;
/**
* Queries the address of a property's data from its name
@@ -52,30 +67,28 @@ public:
* @return Address of the data of the \p name property
* @{
*/
void* UTILS_NULLABLE getPropertyAddress(const char* UTILS_NONNULL name);
void* getPropertyAddress(const char* name);
void const* UTILS_NULLABLE getPropertyAddress(const char* UTILS_NONNULL name) const noexcept;
void const* getPropertyAddress(const char* name) const noexcept;
template<typename T>
inline T* UTILS_NULLABLE getPropertyAddress(const char* UTILS_NONNULL name) {
inline T* getPropertyAddress(const char* name) {
return static_cast<T*>(getPropertyAddress(name));
}
template<typename T>
inline T const* UTILS_NULLABLE getPropertyAddress(const char* UTILS_NONNULL name) const noexcept {
inline T const* getPropertyAddress(const char* name) const noexcept {
return static_cast<T*>(getPropertyAddress(name));
}
template<typename T>
inline bool getPropertyAddress(const char* UTILS_NONNULL name,
T* UTILS_NULLABLE* UTILS_NONNULL p) {
inline bool getPropertyAddress(const char* name, T** p) {
*p = getPropertyAddress<T>(name);
return *p != nullptr;
}
template<typename T>
inline bool getPropertyAddress(const char* UTILS_NONNULL name,
T* const UTILS_NULLABLE* UTILS_NONNULL p) const noexcept {
inline bool getPropertyAddress(const char* name, T* const* p) const noexcept {
*p = getPropertyAddress<T>(name);
return *p != nullptr;
}
@@ -88,12 +101,12 @@ public:
* @return true if the operation was successful, false otherwise.
* @{
*/
bool setProperty(const char* UTILS_NONNULL name, bool v) noexcept;
bool setProperty(const char* UTILS_NONNULL name, int v) noexcept;
bool setProperty(const char* UTILS_NONNULL name, float v) noexcept;
bool setProperty(const char* UTILS_NONNULL name, math::float2 v) noexcept;
bool setProperty(const char* UTILS_NONNULL name, math::float3 v) noexcept;
bool setProperty(const char* UTILS_NONNULL name, math::float4 v) noexcept;
bool setProperty(const char* name, bool v) noexcept;
bool setProperty(const char* name, int v) noexcept;
bool setProperty(const char* name, float v) noexcept;
bool setProperty(const char* name, math::float2 v) noexcept;
bool setProperty(const char* name, math::float3 v) noexcept;
bool setProperty(const char* name, math::float4 v) noexcept;
/** @}*/
/**
@@ -103,20 +116,20 @@ public:
* @return true if the call was successful and \p v was updated
* @{
*/
bool getProperty(const char* UTILS_NONNULL name, bool* UTILS_NONNULL v) const noexcept;
bool getProperty(const char* UTILS_NONNULL name, int* UTILS_NONNULL v) const noexcept;
bool getProperty(const char* UTILS_NONNULL name, float* UTILS_NONNULL v) const noexcept;
bool getProperty(const char* UTILS_NONNULL name, math::float2* UTILS_NONNULL v) const noexcept;
bool getProperty(const char* UTILS_NONNULL name, math::float3* UTILS_NONNULL v) const noexcept;
bool getProperty(const char* UTILS_NONNULL name, math::float4* UTILS_NONNULL v) const noexcept;
bool getProperty(const char* name, bool* v) const noexcept;
bool getProperty(const char* name, int* v) const noexcept;
bool getProperty(const char* name, float* v) const noexcept;
bool getProperty(const char* name, math::float2* v) const noexcept;
bool getProperty(const char* name, math::float3* v) const noexcept;
bool getProperty(const char* name, math::float4* v) const noexcept;
/** @}*/
struct DataSource {
void const* UTILS_NULLABLE data;
void const* data;
size_t count;
};
DataSource getDataSource(const char* UTILS_NONNULL name) const noexcept;
DataSource getDataSource(const char* name) const noexcept;
struct FrameHistory {
using duration_ms = float;
+72 -87
View File
@@ -305,23 +305,11 @@ public:
* @see Engine::getMaxStereoscopicEyes
*/
uint8_t stereoscopicEyeCount = 2;
/*
* Size in MiB of the frame graph texture cache. This should be adjusted based on the
* size of used render targets (typically the screen).
*/
uint32_t resourceAllocatorCacheSizeMB = 64;
/*
* This value determines for how many frames are texture entries kept in the cache.
* The default value of 30 corresponds to about half a second at 60 fps.
*/
uint32_t resourceAllocatorCacheMaxAge = 30;
};
#if UTILS_HAS_THREADING
using CreateCallback = void(void* UTILS_NULLABLE user, void* UTILS_NONNULL token);
using CreateCallback = void(void* user, void* token);
#endif
/**
@@ -360,7 +348,7 @@ public:
*
* @return A reference to this Builder for chaining calls.
*/
Builder& platform(Platform* UTILS_NULLABLE platform) noexcept;
Builder& platform(Platform* platform) noexcept;
/**
* @param config A pointer to optional parameters to specify memory size
@@ -368,7 +356,7 @@ public:
*
* @return A reference to this Builder for chaining calls.
*/
Builder& config(const Config* UTILS_NULLABLE config) noexcept;
Builder& config(const Config* config) noexcept;
/**
* @param sharedContext A platform-dependant context used as a shared context
@@ -376,7 +364,7 @@ public:
*
* @return A reference to this Builder for chaining calls.
*/
Builder& sharedContext(void* UTILS_NULLABLE sharedContext) noexcept;
Builder& sharedContext(void* sharedContext) noexcept;
/**
* @param featureLevel The feature level at which initialize Filament.
@@ -391,7 +379,7 @@ public:
* @param callback Callback called once the engine is initialized and it is safe to
* call Engine::getEngine().
*/
void build(utils::Invocable<void(void* UTILS_NONNULL token)>&& callback) const;
void build(utils::Invocable<void(void* token)>&& callback) const;
#endif
/**
@@ -406,17 +394,16 @@ public:
* allocate the command buffer. If exceptions are disabled, this condition if
* fatal and this function will abort.
*/
Engine* UTILS_NULLABLE build() const;
Engine* build() const;
};
/**
* Backward compatibility helper to create an Engine.
* @see Builder
*/
static inline Engine* UTILS_NULLABLE create(Backend backend = Backend::DEFAULT,
Platform* UTILS_NULLABLE platform = nullptr,
void* UTILS_NULLABLE sharedContext = nullptr,
const Config* UTILS_NULLABLE config = nullptr) {
static inline Engine* create(Backend backend = Backend::DEFAULT,
Platform* platform = nullptr, void* sharedContext = nullptr,
const Config* config = nullptr) {
return Engine::Builder()
.backend(backend)
.platform(platform)
@@ -431,18 +418,16 @@ public:
* Backward compatibility helper to create an Engine asynchronously.
* @see Builder
*/
static inline void createAsync(CreateCallback callback,
void* UTILS_NULLABLE user,
static inline void createAsync(CreateCallback callback, void* user,
Backend backend = Backend::DEFAULT,
Platform* UTILS_NULLABLE platform = nullptr,
void* UTILS_NULLABLE sharedContext = nullptr,
const Config* UTILS_NULLABLE config = nullptr) {
Platform* platform = nullptr, void* sharedContext = nullptr,
const Config* config = nullptr) {
Engine::Builder()
.backend(backend)
.platform(platform)
.sharedContext(sharedContext)
.config(config)
.build([callback, user](void* UTILS_NONNULL token) {
.build([callback, user](void* token) {
callback(user, token);
});
}
@@ -459,7 +444,7 @@ public:
* allocate the command buffer. If exceptions are disabled, this condition if fatal and
* this function will abort.
*/
static Engine* UTILS_NULLABLE getEngine(void* UTILS_NONNULL token);
static Engine* getEngine(void* token);
#endif
@@ -489,7 +474,7 @@ public:
* \remark
* This method is thread-safe.
*/
static void destroy(Engine* UTILS_NULLABLE* UTILS_NULLABLE engine);
static void destroy(Engine** engine);
/**
* Destroy the Engine instance and all associated resources.
@@ -516,7 +501,7 @@ public:
* \remark
* This method is thread-safe.
*/
static void destroy(Engine* UTILS_NULLABLE engine);
static void destroy(Engine* engine);
/**
* Query the feature level supported by the selected backend.
@@ -664,11 +649,11 @@ public:
* `ANativeWindow*`.
* @param flags One or more configuration flags as defined in `SwapChain`.
*
* @return A pointer to the newly created SwapChain.
* @return A pointer to the newly created SwapChain or nullptr if it couldn't be created.
*
* @see Renderer.beginFrame()
*/
SwapChain* UTILS_NONNULL createSwapChain(void* UTILS_NULLABLE nativeWindow, uint64_t flags = 0) noexcept;
SwapChain* createSwapChain(void* nativeWindow, uint64_t flags = 0) noexcept;
/**
@@ -678,42 +663,42 @@ public:
* @param height Height of the drawing buffer in pixels.
* @param flags One or more configuration flags as defined in `SwapChain`.
*
* @return A pointer to the newly created SwapChain.
* @return A pointer to the newly created SwapChain or nullptr if it couldn't be created.
*
* @see Renderer.beginFrame()
*/
SwapChain* UTILS_NONNULL createSwapChain(uint32_t width, uint32_t height, uint64_t flags = 0) noexcept;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags = 0) noexcept;
/**
* Creates a renderer associated to this engine.
*
* A Renderer is intended to map to a *window* on screen.
*
* @return A pointer to the newly created Renderer.
* @return A pointer to the newly created Renderer or nullptr if it couldn't be created.
*/
Renderer* UTILS_NONNULL createRenderer() noexcept;
Renderer* createRenderer() noexcept;
/**
* Creates a View.
*
* @return A pointer to the newly created View.
* @return A pointer to the newly created View or nullptr if it couldn't be created.
*/
View* UTILS_NONNULL createView() noexcept;
View* createView() noexcept;
/**
* Creates a Scene.
*
* @return A pointer to the newly created Scene.
* @return A pointer to the newly created Scene or nullptr if it couldn't be created.
*/
Scene* UTILS_NONNULL createScene() noexcept;
Scene* createScene() noexcept;
/**
* Creates a Camera component.
*
* @param entity Entity to add the camera component to.
* @return A pointer to the newly created Camera.
* @return A pointer to the newly created Camera or nullptr if it couldn't be created.
*/
Camera* UTILS_NONNULL createCamera(utils::Entity entity) noexcept;
Camera* createCamera(utils::Entity entity) noexcept;
/**
* Returns the Camera component of the given entity.
@@ -723,7 +708,7 @@ public:
* have a Camera component. The pointer is valid until destroyCameraComponent()
* is called or the entity itself is destroyed.
*/
Camera* UTILS_NULLABLE getCameraComponent(utils::Entity entity) noexcept;
Camera* getCameraComponent(utils::Entity entity) noexcept;
/**
* Destroys the Camera component associated with the given entity.
@@ -735,17 +720,17 @@ public:
/**
* Creates a Fence.
*
* @return A pointer to the newly created Fence.
* @return A pointer to the newly created Fence or nullptr if it couldn't be created.
*/
Fence* UTILS_NONNULL createFence() noexcept;
Fence* createFence() noexcept;
bool destroy(const BufferObject* UTILS_NULLABLE p); //!< Destroys a BufferObject object.
bool destroy(const VertexBuffer* UTILS_NULLABLE p); //!< Destroys an VertexBuffer object.
bool destroy(const Fence* UTILS_NULLABLE p); //!< Destroys a Fence object.
bool destroy(const IndexBuffer* UTILS_NULLABLE p); //!< Destroys an IndexBuffer object.
bool destroy(const SkinningBuffer* UTILS_NULLABLE p); //!< Destroys a SkinningBuffer object.
bool destroy(const MorphTargetBuffer* UTILS_NULLABLE p); //!< Destroys a MorphTargetBuffer object.
bool destroy(const IndirectLight* UTILS_NULLABLE p); //!< Destroys an IndirectLight object.
bool destroy(const BufferObject* p); //!< Destroys a BufferObject object.
bool destroy(const VertexBuffer* p); //!< Destroys an VertexBuffer object.
bool destroy(const Fence* p); //!< Destroys a Fence object.
bool destroy(const IndexBuffer* p); //!< Destroys an IndexBuffer object.
bool destroy(const SkinningBuffer* p); //!< Destroys a SkinningBuffer object.
bool destroy(const MorphTargetBuffer* p); //!< Destroys a MorphTargetBuffer object.
bool destroy(const IndirectLight* p); //!< Destroys an IndirectLight object.
/**
* Destroys a Material object
@@ -755,38 +740,38 @@ public:
* @exception utils::PreConditionPanic is thrown if some MaterialInstances remain.
* no-op if exceptions are disabled and some MaterialInstances remain.
*/
bool destroy(const Material* UTILS_NULLABLE p);
bool destroy(const MaterialInstance* UTILS_NULLABLE p); //!< Destroys a MaterialInstance object.
bool destroy(const Renderer* UTILS_NULLABLE p); //!< Destroys a Renderer object.
bool destroy(const Scene* UTILS_NULLABLE p); //!< Destroys a Scene object.
bool destroy(const Skybox* UTILS_NULLABLE p); //!< Destroys a SkyBox object.
bool destroy(const ColorGrading* UTILS_NULLABLE p); //!< Destroys a ColorGrading object.
bool destroy(const SwapChain* UTILS_NULLABLE p); //!< Destroys a SwapChain object.
bool destroy(const Stream* UTILS_NULLABLE p); //!< Destroys a Stream object.
bool destroy(const Texture* UTILS_NULLABLE p); //!< Destroys a Texture object.
bool destroy(const RenderTarget* UTILS_NULLABLE p); //!< Destroys a RenderTarget object.
bool destroy(const View* UTILS_NULLABLE p); //!< Destroys a View object.
bool destroy(const InstanceBuffer* UTILS_NULLABLE p); //!< Destroys an InstanceBuffer object.
void destroy(utils::Entity e); //!< Destroys all filament-known components from this entity
bool destroy(const Material* p);
bool destroy(const MaterialInstance* p); //!< Destroys a MaterialInstance object.
bool destroy(const Renderer* p); //!< Destroys a Renderer object.
bool destroy(const Scene* p); //!< Destroys a Scene object.
bool destroy(const Skybox* p); //!< Destroys a SkyBox object.
bool destroy(const ColorGrading* p); //!< Destroys a ColorGrading object.
bool destroy(const SwapChain* p); //!< Destroys a SwapChain object.
bool destroy(const Stream* p); //!< Destroys a Stream object.
bool destroy(const Texture* p); //!< Destroys a Texture object.
bool destroy(const RenderTarget* p); //!< Destroys a RenderTarget object.
bool destroy(const View* p); //!< Destroys a View object.
bool destroy(const InstanceBuffer* p); //!< Destroys an InstanceBuffer object.
void destroy(utils::Entity e); //!< Destroys all filament-known components from this entity
bool isValid(const BufferObject* UTILS_NULLABLE p); //!< Tells whether a BufferObject object is valid
bool isValid(const VertexBuffer* UTILS_NULLABLE p); //!< Tells whether an VertexBuffer object is valid
bool isValid(const Fence* UTILS_NULLABLE p); //!< Tells whether a Fence object is valid
bool isValid(const IndexBuffer* UTILS_NULLABLE p); //!< Tells whether an IndexBuffer object is valid
bool isValid(const SkinningBuffer* UTILS_NULLABLE p); //!< Tells whether a SkinningBuffer object is valid
bool isValid(const MorphTargetBuffer* UTILS_NULLABLE p); //!< Tells whether a MorphTargetBuffer object is valid
bool isValid(const IndirectLight* UTILS_NULLABLE p); //!< Tells whether an IndirectLight object is valid
bool isValid(const Material* UTILS_NULLABLE p); //!< Tells whether an IndirectLight object is valid
bool isValid(const Renderer* UTILS_NULLABLE p); //!< Tells whether a Renderer object is valid
bool isValid(const Scene* UTILS_NULLABLE p); //!< Tells whether a Scene object is valid
bool isValid(const Skybox* UTILS_NULLABLE p); //!< Tells whether a SkyBox object is valid
bool isValid(const ColorGrading* UTILS_NULLABLE p); //!< Tells whether a ColorGrading object is valid
bool isValid(const SwapChain* UTILS_NULLABLE p); //!< Tells whether a SwapChain object is valid
bool isValid(const Stream* UTILS_NULLABLE p); //!< Tells whether a Stream object is valid
bool isValid(const Texture* UTILS_NULLABLE p); //!< Tells whether a Texture object is valid
bool isValid(const RenderTarget* UTILS_NULLABLE p); //!< Tells whether a RenderTarget object is valid
bool isValid(const View* UTILS_NULLABLE p); //!< Tells whether a View object is valid
bool isValid(const InstanceBuffer* UTILS_NULLABLE p); //!< Tells whether an InstanceBuffer object is valid
bool isValid(const BufferObject* p); //!< Tells whether a BufferObject object is valid
bool isValid(const VertexBuffer* p); //!< Tells whether an VertexBuffer object is valid
bool isValid(const Fence* p); //!< Tells whether a Fence object is valid
bool isValid(const IndexBuffer* p); //!< Tells whether an IndexBuffer object is valid
bool isValid(const SkinningBuffer* p); //!< Tells whether a SkinningBuffer object is valid
bool isValid(const MorphTargetBuffer* p); //!< Tells whether a MorphTargetBuffer object is valid
bool isValid(const IndirectLight* p); //!< Tells whether an IndirectLight object is valid
bool isValid(const Material* p); //!< Tells whether an IndirectLight object is valid
bool isValid(const Renderer* p); //!< Tells whether a Renderer object is valid
bool isValid(const Scene* p); //!< Tells whether a Scene object is valid
bool isValid(const Skybox* p); //!< Tells whether a SkyBox object is valid
bool isValid(const ColorGrading* p); //!< Tells whether a ColorGrading object is valid
bool isValid(const SwapChain* p); //!< Tells whether a SwapChain object is valid
bool isValid(const Stream* p); //!< Tells whether a Stream object is valid
bool isValid(const Texture* p); //!< Tells whether a Texture object is valid
bool isValid(const RenderTarget* p); //!< Tells whether a RenderTarget object is valid
bool isValid(const View* p); //!< Tells whether a View object is valid
bool isValid(const InstanceBuffer* p); //!< Tells whether an InstanceBuffer object is valid
/**
* Kicks the hardware thread (e.g. the OpenGL, Vulkan or Metal thread) and blocks until
@@ -826,7 +811,7 @@ public:
*
* @return A pointer to the default Material instance (a singleton).
*/
Material const* UTILS_NONNULL getDefaultMaterial() const noexcept;
const Material* getDefaultMaterial() const noexcept;
/**
* Returns the resolved backend.
@@ -857,7 +842,7 @@ public:
* @return A pointer to the Platform object that was provided to Engine::create, or the
* Filament-created one.
*/
Platform* UTILS_NULLABLE getPlatform() const noexcept;
Platform* getPlatform() const noexcept;
/**
* Allocate a small amount of memory directly in the command stream. The allocated memory is
@@ -870,7 +855,7 @@ public:
* @note there is no need to destroy this buffer, it will be freed automatically when
* the current command buffer is executed.
*/
void* UTILS_NULLABLE streamAlloc(size_t size, size_t alignment = alignof(double)) noexcept;
void* streamAlloc(size_t size, size_t alignment = alignof(double)) noexcept;
/**
* Invokes one iteration of the render loop, used only on single-threaded platforms.
+1 -1
View File
@@ -76,7 +76,7 @@ public:
* @return FenceStatus::CONDITION_SATISFIED on success,
* FenceStatus::ERROR otherwise.
*/
static FenceStatus waitAndDestroy(Fence* UTILS_NONNULL fence, Mode mode = Mode::FLUSH);
static FenceStatus waitAndDestroy(Fence* fence, Mode mode = Mode::FLUSH);
protected:
// prevent heap allocation
+2 -2
View File
@@ -79,14 +79,14 @@ public:
* @param planes six plane equations encoded as in getNormalizedPlane() in
* left, right, bottom, top, far, near order
*/
void getNormalizedPlanes(math::float4 planes[UTILS_NONNULL 6]) const noexcept;
void getNormalizedPlanes(math::float4 planes[6]) const noexcept;
/**
* Returns all six frustum planes in left, right, bottom, top, far, near order
* @return six plane equations encoded as in getNormalizedPlane() in
* left, right, bottom, top, far, near order
*/
math::float4 const* UTILS_NONNULL getNormalizedPlanes() const noexcept { return mPlanes; }
math::float4 const* getNormalizedPlanes() const noexcept { return mPlanes; }
/**
* Returns whether a box intersects the frustum (i.e. is visible)
+3 -2
View File
@@ -89,7 +89,8 @@ public:
*
* @param engine Reference to the filament::Engine to associate this IndexBuffer with.
*
* @return pointer to the newly created object.
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
*
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
* memory or other resources.
@@ -97,7 +98,7 @@ public:
*
* @see IndexBuffer::setBuffer
*/
IndexBuffer* UTILS_NONNULL build(Engine& engine);
IndexBuffer* build(Engine& engine);
private:
friend class FIndexBuffer;
};
+9 -10
View File
@@ -116,7 +116,7 @@ public:
* @return This Builder, for chaining calls.
*
*/
Builder& reflections(Texture const* UTILS_NULLABLE cubemap) noexcept;
Builder& reflections(Texture const* cubemap) noexcept;
/**
* Sets the irradiance as Spherical Harmonics.
@@ -162,7 +162,7 @@ public:
* Because the coefficients are pre-scaled, `sh[0]` is the environment's
* average irradiance.
*/
Builder& irradiance(uint8_t bands, math::float3 const* UTILS_NONNULL sh) noexcept;
Builder& irradiance(uint8_t bands, math::float3 const* sh) noexcept;
/**
* Sets the irradiance from the radiance expressed as Spherical Harmonics.
@@ -194,7 +194,7 @@ public:
*
* @return This Builder, for chaining calls.
*/
Builder& radiance(uint8_t bands, math::float3 const* UTILS_NONNULL sh) noexcept;
Builder& radiance(uint8_t bands, math::float3 const* sh) noexcept;
/**
* Sets the irradiance as a cubemap.
@@ -213,7 +213,7 @@ public:
*
* @see irradiance(uint8_t bands, math::float3 const* sh)
*/
Builder& irradiance(Texture const* UTILS_NULLABLE cubemap) noexcept;
Builder& irradiance(Texture const* cubemap) noexcept;
/**
* (optional) Environment intensity.
@@ -249,7 +249,7 @@ public:
* memory or other resources.
* @exception utils::PreConditionPanic if a parameter to a builder function was invalid.
*/
IndirectLight* UTILS_NONNULL build(Engine& engine);
IndirectLight* build(Engine& engine);
private:
friend class FIndirectLight;
@@ -286,12 +286,12 @@ public:
/**
* Returns the associated reflection map, or null if it does not exist.
*/
Texture const* UTILS_NULLABLE getReflectionsTexture() const noexcept;
Texture const* getReflectionsTexture() const noexcept;
/**
* Returns the associated irradiance map, or null if it does not exist.
*/
Texture const* UTILS_NULLABLE getIrradianceTexture() const noexcept;
Texture const* getIrradianceTexture() const noexcept;
/**
* Helper to estimate the direction of the dominant light in the environment represented by
@@ -314,7 +314,7 @@ public:
* @see LightManager::Builder::direction()
* @see getColorEstimate()
*/
static math::float3 getDirectionEstimate(const math::float3 sh[UTILS_NONNULL 9]) noexcept;
static math::float3 getDirectionEstimate(const math::float3 sh[9]) noexcept;
/**
* Helper to estimate the color and relative intensity of the environment represented by
@@ -334,8 +334,7 @@ public:
* @see LightManager::Builder::intensity()
* @see getDirectionEstimate, getIntensity, setIntensity
*/
static math::float4 getColorEstimate(const math::float3 sh[UTILS_NONNULL 9],
math::float3 direction) noexcept;
static math::float4 getColorEstimate(const math::float3 sh[9], math::float3 direction) noexcept;
/** @deprecated use static versions instead */
+3 -4
View File
@@ -68,12 +68,12 @@ public:
* @param localTransforms an array of math::mat4f with length instanceCount, must remain
* valid until after build() is called
*/
Builder& localTransforms(math::mat4f const* UTILS_NULLABLE localTransforms) noexcept;
Builder& localTransforms(math::mat4f const* localTransforms) noexcept;
/**
* Creates the InstanceBuffer object and returns a pointer to it.
*/
InstanceBuffer* UTILS_NONNULL build(Engine& engine);
InstanceBuffer* build(Engine& engine);
private:
friend class FInstanceBuffer;
@@ -93,8 +93,7 @@ public:
* @param count the number of local transforms
* @param offset index of the first instance to set local transforms
*/
void setLocalTransforms(math::mat4f const* UTILS_NONNULL localTransforms,
size_t count, size_t offset = 0);
void setLocalTransforms(math::mat4f const* localTransforms, size_t count, size_t offset = 0);
protected:
// prevent heap allocation
+4 -4
View File
@@ -176,7 +176,7 @@ public:
* Retrieve the Entities of all the components of this manager.
* @return A list, in no particular order, of all the entities managed by this manager.
*/
utils::Entity const* UTILS_NONNULL getEntities() const noexcept;
utils::Entity const* getEntities() const noexcept;
/**
* Gets an Instance representing the Light component associated with the given Entity.
@@ -394,7 +394,7 @@ public:
* positions into
* @param cascades the number of shadow cascades, at most 4
*/
static void computeUniformSplits(float* UTILS_NONNULL splitPositions, uint8_t cascades);
static void computeUniformSplits(float* splitPositions, uint8_t cascades);
/**
* Utility method to compute ShadowOptions::cascadeSplitPositions according to a logarithmic
@@ -406,7 +406,7 @@ public:
* @param near the camera near plane
* @param far the camera far plane
*/
static void computeLogSplits(float* UTILS_NONNULL splitPositions, uint8_t cascades,
static void computeLogSplits(float* splitPositions, uint8_t cascades,
float near, float far);
/**
@@ -426,7 +426,7 @@ public:
* @param lambda a float in the range [0, 1] that interpolates between log and
* uniform split schemes
*/
static void computePracticalSplits(float* UTILS_NONNULL splitPositions, uint8_t cascades,
static void computePracticalSplits(float* splitPositions, uint8_t cascades,
float near, float far, float lambda);
};
+26 -26
View File
@@ -74,7 +74,7 @@ public:
*/
struct ParameterInfo {
//! Name of the parameter.
const char* UTILS_NONNULL name;
const char* name;
//! Whether the parameter is a sampler (texture).
bool isSampler;
//! Whether the parameter is a subpass type.
@@ -110,7 +110,7 @@ public:
* @param payload Pointer to the material data, must stay valid until build() is called.
* @param size Size of the material data pointed to by "payload" in bytes.
*/
Builder& package(const void* UTILS_NONNULL payload, size_t size);
Builder& package(const void* payload, size_t size);
template<typename T>
using is_supported_constant_parameter_t = typename std::enable_if<
@@ -132,11 +132,11 @@ public:
* in the material definition.
*/
template<typename T, typename = is_supported_constant_parameter_t<T>>
Builder& constant(const char* UTILS_NONNULL name, size_t nameLength, T value);
Builder& constant(const char* name, size_t nameLength, T value);
/** inline helper to provide the constant name as a null-terminated C string */
template<typename T, typename = is_supported_constant_parameter_t<T>>
inline Builder& constant(const char* UTILS_NONNULL name, T value) {
inline Builder& constant(const char* name, T value) {
return constant(name, strlen(name), value);
}
@@ -152,7 +152,7 @@ public:
* memory or other resources.
* @exception utils::PreConditionPanic if a parameter to a builder function was invalid.
*/
Material* UTILS_NULLABLE build(Engine& engine);
Material* build(Engine& engine);
private:
friend class FMaterial;
};
@@ -198,22 +198,22 @@ public:
*/
void compile(CompilerPriorityQueue priority,
UserVariantFilterMask variants,
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
utils::Invocable<void(Material* UTILS_NONNULL)>&& callback = {}) noexcept;
backend::CallbackHandler* handler = nullptr,
utils::Invocable<void(Material*)>&& callback = {}) noexcept;
inline void compile(CompilerPriorityQueue priority,
UserVariantFilterBit variants,
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
utils::Invocable<void(Material* UTILS_NONNULL)>&& callback = {}) noexcept {
backend::CallbackHandler* handler = nullptr,
utils::Invocable<void(Material*)>&& callback = {}) noexcept {
compile(priority, UserVariantFilterMask(variants), handler,
std::forward<utils::Invocable<void(Material* UTILS_NONNULL)>>(callback));
std::forward<utils::Invocable<void(Material*)>>(callback));
}
inline void compile(CompilerPriorityQueue priority,
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
utils::Invocable<void(Material* UTILS_NONNULL)>&& callback = {}) noexcept {
backend::CallbackHandler* handler = nullptr,
utils::Invocable<void(Material*)>&& callback = {}) noexcept {
compile(priority, UserVariantFilterBit::ALL, handler,
std::forward<utils::Invocable<void(Material* UTILS_NONNULL)>>(callback));
std::forward<utils::Invocable<void(Material*)>>(callback));
}
/**
@@ -225,13 +225,13 @@ public:
*
* @return A pointer to the new instance.
*/
MaterialInstance* UTILS_NONNULL createInstance(const char* UTILS_NULLABLE name = nullptr) const noexcept;
MaterialInstance* createInstance(const char* name = nullptr) const noexcept;
//! Returns the name of this material as a null-terminated string.
const char* UTILS_NONNULL getName() const noexcept;
const char* getName() const noexcept;
//! Returns the shading model of this material.
Shading getShading() const noexcept;
Shading getShading() const noexcept;
//! Returns the interpolation mode of this material. This affects how variables are interpolated.
Interpolation getInterpolation() const noexcept;
@@ -317,13 +317,13 @@ public:
*
* @return The number of parameters written to the parameters pointer.
*/
size_t getParameters(ParameterInfo* UTILS_NONNULL parameters, size_t count) const noexcept;
size_t getParameters(ParameterInfo* parameters, size_t count) const noexcept;
//! Indicates whether a parameter of the given name exists on this material.
bool hasParameter(const char* UTILS_NONNULL name) const noexcept;
bool hasParameter(const char* name) const noexcept;
//! Indicates whether an existing parameter is a sampler or not.
bool isSampler(const char* UTILS_NONNULL name) const noexcept;
bool isSampler(const char* name) const noexcept;
/**
* Sets the value of the given parameter on this material's default instance.
@@ -334,7 +334,7 @@ public:
* @see getDefaultInstance()
*/
template <typename T>
void setDefaultParameter(const char* UTILS_NONNULL name, T value) noexcept {
void setDefaultParameter(const char* name, T value) noexcept {
getDefaultInstance()->setParameter(name, value);
}
@@ -347,8 +347,8 @@ public:
*
* @see getDefaultInstance()
*/
void setDefaultParameter(const char* UTILS_NONNULL name,
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) noexcept {
void setDefaultParameter(const char* name, Texture const* texture,
TextureSampler const& sampler) noexcept {
getDefaultInstance()->setParameter(name, texture, sampler);
}
@@ -361,7 +361,7 @@ public:
*
* @see getDefaultInstance()
*/
void setDefaultParameter(const char* UTILS_NONNULL name, RgbType type, math::float3 color) noexcept {
void setDefaultParameter(const char* name, RgbType type, math::float3 color) noexcept {
getDefaultInstance()->setParameter(name, type, color);
}
@@ -374,15 +374,15 @@ public:
*
* @see getDefaultInstance()
*/
void setDefaultParameter(const char* UTILS_NONNULL name, RgbaType type, math::float4 color) noexcept {
void setDefaultParameter(const char* name, RgbaType type, math::float4 color) noexcept {
getDefaultInstance()->setParameter(name, type, color);
}
//! Returns this material's default instance.
MaterialInstance* UTILS_NONNULL getDefaultInstance() noexcept;
MaterialInstance* getDefaultInstance() noexcept;
//! Returns this material's default instance.
MaterialInstance const* UTILS_NONNULL getDefaultInstance() const noexcept;
MaterialInstance const* getDefaultInstance() const noexcept;
protected:
// prevent heap allocation
+18 -23
View File
@@ -47,7 +47,7 @@ class UTILS_PUBLIC MaterialInstance : public FilamentAPI {
using StringLiteralHelper = const char[N];
struct StringLiteral {
const char* UTILS_NONNULL data;
const char* data;
size_t size;
template<size_t N>
StringLiteral(StringLiteralHelper<N> const& s) noexcept // NOLINT(google-explicit-constructor)
@@ -95,18 +95,17 @@ public:
* @param name A name for the new MaterialInstance or nullptr to use the template's name
* @return A new MaterialInstance
*/
static MaterialInstance* UTILS_NONNULL duplicate(MaterialInstance const* UTILS_NONNULL other,
const char* UTILS_NULLABLE name = nullptr) noexcept;
static MaterialInstance* duplicate(MaterialInstance const* other, const char* name = nullptr) noexcept;
/**
* @return the Material associated with this instance
*/
Material const* UTILS_NONNULL getMaterial() const noexcept;
Material const* getMaterial() const noexcept;
/**
* @return the name associated with this instance
*/
const char* UTILS_NONNULL getName() const noexcept;
const char* getName() const noexcept;
/**
* Set a uniform by name
@@ -117,7 +116,7 @@ public:
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
*/
template<typename T, typename = is_supported_parameter_t<T>>
void setParameter(const char* UTILS_NONNULL name, size_t nameLength, T const& value);
void setParameter(const char* name, size_t nameLength, T const& value);
/** inline helper to provide the name as a null-terminated string literal */
template<typename T, typename = is_supported_parameter_t<T>>
@@ -127,7 +126,7 @@ public:
/** inline helper to provide the name as a null-terminated C string */
template<typename T, typename = is_supported_parameter_t<T>>
inline void setParameter(const char* UTILS_NONNULL name, T const& value) {
inline void setParameter(const char* name, T const& value) {
setParameter<T>(name, strlen(name), value);
}
@@ -142,19 +141,17 @@ public:
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
*/
template<typename T, typename = is_supported_parameter_t<T>>
void setParameter(const char* UTILS_NONNULL name, size_t nameLength,
const T* UTILS_NONNULL values, size_t count);
void setParameter(const char* name, size_t nameLength, const T* values, size_t count);
/** inline helper to provide the name as a null-terminated string literal */
template<typename T, typename = is_supported_parameter_t<T>>
inline void setParameter(StringLiteral name, const T* UTILS_NONNULL values, size_t count) {
inline void setParameter(StringLiteral name, const T* values, size_t count) {
setParameter<T>(name.data, name.size, values, count);
}
/** inline helper to provide the name as a null-terminated C string */
template<typename T, typename = is_supported_parameter_t<T>>
inline void setParameter(const char* UTILS_NONNULL name,
const T* UTILS_NONNULL values, size_t count) {
inline void setParameter(const char* name, const T* values, size_t count) {
setParameter<T>(name, strlen(name), values, count);
}
@@ -171,18 +168,18 @@ public:
* @param sampler Sampler parameters.
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
*/
void setParameter(const char* UTILS_NONNULL name, size_t nameLength,
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler);
void setParameter(const char* name, size_t nameLength,
Texture const* texture, TextureSampler const& sampler);
/** inline helper to provide the name as a null-terminated string literal */
inline void setParameter(StringLiteral name,
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) {
Texture const* texture, TextureSampler const& sampler) {
setParameter(name.data, name.size, texture, sampler);
}
/** inline helper to provide the name as a null-terminated C string */
inline void setParameter(const char* UTILS_NONNULL name,
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) {
inline void setParameter(const char* name,
Texture const* texture, TextureSampler const& sampler) {
setParameter(name, strlen(name), texture, sampler);
}
@@ -197,8 +194,7 @@ public:
* @param color Array of read, green, blue channels values.
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
*/
void setParameter(const char* UTILS_NONNULL name, size_t nameLength,
RgbType type, math::float3 color);
void setParameter(const char* name, size_t nameLength, RgbType type, math::float3 color);
/** inline helper to provide the name as a null-terminated string literal */
inline void setParameter(StringLiteral name, RgbType type, math::float3 color) {
@@ -206,7 +202,7 @@ public:
}
/** inline helper to provide the name as a null-terminated C string */
inline void setParameter(const char* UTILS_NONNULL name, RgbType type, math::float3 color) {
inline void setParameter(const char* name, RgbType type, math::float3 color) {
setParameter(name, strlen(name), type, color);
}
@@ -221,8 +217,7 @@ public:
* @param color Array of read, green, blue and alpha channels values.
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
*/
void setParameter(const char* UTILS_NONNULL name, size_t nameLength,
RgbaType type, math::float4 color);
void setParameter(const char* name, size_t nameLength, RgbaType type, math::float4 color);
/** inline helper to provide the name as a null-terminated string literal */
inline void setParameter(StringLiteral name, RgbaType type, math::float4 color) {
@@ -230,7 +225,7 @@ public:
}
/** inline helper to provide the name as a null-terminated C string */
inline void setParameter(const char* UTILS_NONNULL name, RgbaType type, math::float4 color) {
inline void setParameter(const char* name, RgbaType type, math::float4 color) {
setParameter(name, strlen(name), type, color);
}
@@ -68,13 +68,14 @@ public:
*
* @param engine Reference to the filament::Engine to associate this MorphTargetBuffer with.
*
* @return pointer to the newly created object.
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
*
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
* memory or other resources.
* @exception utils::PreConditionPanic if a parameter to a builder function was invalid.
*/
MorphTargetBuffer* UTILS_NONNULL build(Engine& engine);
MorphTargetBuffer* build(Engine& engine);
private:
friend class FMorphTargetBuffer;
};
@@ -94,7 +95,7 @@ public:
* @see setTangentsAt
*/
void setPositionsAt(Engine& engine, size_t targetIndex,
math::float3 const* UTILS_NONNULL positions, size_t count, size_t offset = 0);
math::float3 const* positions, size_t count, size_t offset = 0);
/**
* Updates positions for the given morph target.
@@ -109,7 +110,7 @@ public:
* @see setTangentsAt
*/
void setPositionsAt(Engine& engine, size_t targetIndex,
math::float4 const* UTILS_NONNULL positions, size_t count, size_t offset = 0);
math::float4 const* positions, size_t count, size_t offset = 0);
/**
* Updates tangents for the given morph target.
@@ -125,7 +126,7 @@ public:
* @see setPositionsAt
*/
void setTangentsAt(Engine& engine, size_t targetIndex,
math::short4 const* UTILS_NONNULL tangents, size_t count, size_t offset = 0);
math::short4 const* tangents, size_t count, size_t offset = 0);
/**
* Returns the vertex count of this MorphTargetBuffer.
+5 -4
View File
@@ -106,7 +106,7 @@ public:
* @param texture The associated texture object.
* @return A reference to this Builder for chaining calls.
*/
Builder& texture(AttachmentPoint attachment, Texture* UTILS_NULLABLE texture) noexcept;
Builder& texture(AttachmentPoint attachment, Texture* texture) noexcept;
/**
* Sets the mipmap level for a given attachment point.
@@ -138,9 +138,10 @@ public:
/**
* Creates the RenderTarget object and returns a pointer to it.
*
* @return pointer to the newly created object.
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
*/
RenderTarget* UTILS_NONNULL build(Engine& engine);
RenderTarget* build(Engine& engine);
private:
friend class FRenderTarget;
@@ -151,7 +152,7 @@ public:
* @param attachment Attachment point
* @return A Texture object or nullptr if no texture is set for this attachment point
*/
Texture* UTILS_NULLABLE getTexture(AttachmentPoint attachment) const noexcept;
Texture* getTexture(AttachmentPoint attachment) const noexcept;
/**
* Returns the mipmap level set on the given attachment point
+34 -61
View File
@@ -129,7 +129,7 @@ public:
* Retrieve the Entities of all the components of this manager.
* @return A list, in no particular order, of all the entities managed by this manager.
*/
utils::Entity const* UTILS_NONNULL getEntities() const noexcept;
utils::Entity const* getEntities() const noexcept;
/**
* The transformation associated with a skinning joint.
@@ -190,19 +190,9 @@ public:
* @param maxIndex specifies the maximum index contained in the index buffer
* @param count number of indices to read (for triangles, this should be a multiple of 3)
*/
Builder& geometry(size_t index, PrimitiveType type,
VertexBuffer* UTILS_NONNULL vertices,
IndexBuffer* UTILS_NONNULL indices,
size_t offset, size_t minIndex, size_t maxIndex, size_t count) noexcept;
Builder& geometry(size_t index, PrimitiveType type,
VertexBuffer* UTILS_NONNULL vertices,
IndexBuffer* UTILS_NONNULL indices,
size_t offset, size_t count) noexcept; //!< \overload
Builder& geometry(size_t index, PrimitiveType type,
VertexBuffer* UTILS_NONNULL vertices,
IndexBuffer* UTILS_NONNULL indices) noexcept; //!< \overload
Builder& geometry(size_t index, PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices, size_t offset, size_t minIndex, size_t maxIndex, size_t count) noexcept;
Builder& geometry(size_t index, PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices, size_t offset, size_t count) noexcept; //!< \overload
Builder& geometry(size_t index, PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices) noexcept; //!< \overload
/**
* Binds a material instance to the specified primitive.
@@ -219,8 +209,7 @@ public:
*
* @see Engine::setActiveFeatureLevel
*/
Builder& material(size_t index,
MaterialInstance const* UTILS_NONNULL materialInstance) noexcept;
Builder& material(size_t index, MaterialInstance const* materialInstance) noexcept;
/**
* The axis-aligned bounding box of the renderable.
@@ -368,8 +357,7 @@ public:
* @param count 0 to disable, otherwise the number of bone transforms (up to 255)
* @param offset offset in the SkinningBuffer
*/
Builder& skinning(SkinningBuffer* UTILS_NONNULL skinningBuffer,
size_t count, size_t offset) noexcept;
Builder& skinning(SkinningBuffer* skinningBuffer, size_t count, size_t offset) noexcept;
/**
@@ -387,8 +375,8 @@ public:
* @param boneCount 0 to disable, otherwise the number of bone transforms (up to 255)
* @param transforms the initial set of transforms (one for each bone)
*/
Builder& skinning(size_t boneCount, math::mat4f const* UTILS_NONNULL transforms) noexcept;
Builder& skinning(size_t boneCount, Bone const* UTILS_NONNULL bones) noexcept; //!< \overload
Builder& skinning(size_t boneCount, math::mat4f const* transforms) noexcept;
Builder& skinning(size_t boneCount, Bone const* bones) noexcept; //!< \overload
Builder& skinning(size_t boneCount) noexcept; //!< \overload
/**
@@ -417,8 +405,7 @@ public:
* @see VertexBuffer:Builder:advancedSkinning
*/
Builder& boneIndicesAndWeights(size_t primitiveIndex,
math::float2 const* UTILS_NONNULL indicesAndWeights,
size_t count, size_t bonesPerVertex) noexcept;
math::float2 const* indicesAndWeights, size_t count, size_t bonesPerVertex) noexcept;
/**
* Define bone indices and weights "pairs" for vertex skinning as a float2.
@@ -481,11 +468,10 @@ public:
* @param count number of vertices in the morph target buffer to read, must equal the geometry's count (for triangles, this should be a multiple of 3)
*/
Builder& morphing(uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer,
size_t offset, size_t count) noexcept;
MorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count) noexcept;
inline Builder& morphing(uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) noexcept;
MorphTargetBuffer* morphTargetBuffer) noexcept;
/**
* Sets the drawing order for blended primitives. The drawing order is either global or
@@ -552,8 +538,7 @@ public:
* the result of Engine::getMaxAutomaticInstances().
* @param instanceBuffer an InstanceBuffer containing at least instanceCount transforms
*/
Builder& instances(size_t instanceCount,
InstanceBuffer* UTILS_NONNULL instanceBuffer) noexcept;
Builder& instances(size_t instanceCount, InstanceBuffer* instanceBuffer) noexcept;
/**
* Adds the Renderable component to an entity.
@@ -580,18 +565,18 @@ public:
friend class FRenderPrimitive;
friend class FRenderableManager;
struct Entry {
VertexBuffer* UTILS_NULLABLE vertices = nullptr;
IndexBuffer* UTILS_NULLABLE indices = nullptr;
VertexBuffer* vertices = nullptr;
IndexBuffer* indices = nullptr;
size_t offset = 0;
size_t minIndex = 0;
size_t maxIndex = 0;
size_t count = 0;
MaterialInstance const* UTILS_NULLABLE materialInstance = nullptr;
MaterialInstance const* materialInstance = nullptr;
PrimitiveType type = PrimitiveType::TRIANGLES;
uint16_t blendOrder = 0;
bool globalBlendOrderEnabled = false;
struct {
MorphTargetBuffer* UTILS_NULLABLE buffer = nullptr;
MorphTargetBuffer* buffer = nullptr;
size_t offset = 0;
size_t count = 0;
} morphing;
@@ -709,11 +694,8 @@ public:
* Updates the bone transforms in the range [offset, offset + boneCount).
* The bones must be pre-allocated using Builder::skinning().
*/
void setBones(Instance instance, Bone const* UTILS_NONNULL transforms,
size_t boneCount = 1, size_t offset = 0);
void setBones(Instance instance, math::mat4f const* UTILS_NONNULL transforms,
size_t boneCount = 1, size_t offset = 0); //!< \overload
void setBones(Instance instance, Bone const* transforms, size_t boneCount = 1, size_t offset = 0);
void setBones(Instance instance, math::mat4f const* transforms, size_t boneCount = 1, size_t offset = 0); //!< \overload
/**
* Associates a region of a SkinningBuffer to a renderable instance
@@ -726,7 +708,7 @@ public:
* @param count Size of the region in bones, must be smaller or equal to 256.
* @param offset Start offset of the region in bones
*/
void setSkinningBuffer(Instance instance, SkinningBuffer* UTILS_NONNULL skinningBuffer,
void setSkinningBuffer(Instance instance, SkinningBuffer* skinningBuffer,
size_t count, size_t offset);
/**
@@ -741,25 +723,24 @@ public:
* @param offset Index of the first morph target weight to set at instance.
*/
void setMorphWeights(Instance instance,
float const* UTILS_NONNULL weights, size_t count, size_t offset = 0);
float const* weights, size_t count, size_t offset = 0);
/**
* Associates a MorphTargetBuffer to the given primitive.
*/
void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer, size_t offset, size_t count);
MorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count);
/**
* Utility method to change a MorphTargetBuffer to the given primitive
*/
inline void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer);
MorphTargetBuffer* morphTargetBuffer);
/**
* Get a MorphTargetBuffer to the given primitive or null if it doesn't exist.
*/
MorphTargetBuffer* UTILS_NULLABLE getMorphTargetBufferAt(Instance instance,
uint8_t level, size_t primitiveIndex) const noexcept;
MorphTargetBuffer* getMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex) const noexcept;
/**
* Gets the number of morphing in the given entity.
@@ -801,22 +782,20 @@ public:
* @see Engine::setActiveFeatureLevel
*/
void setMaterialInstanceAt(Instance instance,
size_t primitiveIndex, MaterialInstance const* UTILS_NONNULL materialInstance);
size_t primitiveIndex, MaterialInstance const* materialInstance);
/**
* Retrieves the material instance that is bound to the given primitive.
*/
MaterialInstance* UTILS_NULLABLE getMaterialInstanceAt(
Instance instance, size_t primitiveIndex) const noexcept;
MaterialInstance* getMaterialInstanceAt(Instance instance, size_t primitiveIndex) const noexcept;
/**
* Changes the geometry for the given primitive.
*
* \see Builder::geometry()
*/
void setGeometryAt(Instance instance, size_t primitiveIndex, PrimitiveType type,
VertexBuffer* UTILS_NONNULL vertices,
IndexBuffer* UTILS_NONNULL indices,
void setGeometryAt(Instance instance, size_t primitiveIndex,
PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices,
size_t offset, size_t count) noexcept;
/**
@@ -877,9 +856,7 @@ public:
template<typename VECTOR, typename INDEX,
typename = typename is_supported_vector_type<VECTOR>::type,
typename = typename is_supported_index_type<INDEX>::type>
static Box computeAABB(
VECTOR const* UTILS_NONNULL vertices,
INDEX const* UTILS_NONNULL indices, size_t count,
static Box computeAABB(VECTOR const* vertices, INDEX const* indices, size_t count,
size_t stride = sizeof(VECTOR)) noexcept;
protected:
@@ -887,25 +864,21 @@ protected:
~RenderableManager() = default;
};
RenderableManager::Builder& RenderableManager::Builder::morphing(
uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) noexcept {
RenderableManager::Builder& RenderableManager::Builder::morphing(uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* morphTargetBuffer) noexcept {
return morphing(level, primitiveIndex, morphTargetBuffer, 0,
morphTargetBuffer->getVertexCount());
}
void RenderableManager::setMorphTargetBufferAt(
Instance instance, uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) {
void RenderableManager::setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* morphTargetBuffer) {
setMorphTargetBufferAt(instance, level, primitiveIndex, morphTargetBuffer, 0,
morphTargetBuffer->getVertexCount());
}
template<typename VECTOR, typename INDEX, typename, typename>
Box RenderableManager::computeAABB(
VECTOR const* UTILS_NONNULL vertices,
INDEX const* UTILS_NONNULL indices,
size_t count, size_t stride) noexcept {
Box RenderableManager::computeAABB(VECTOR const* vertices, INDEX const* indices, size_t count,
size_t stride) noexcept {
math::float3 bmin(FLT_MAX);
math::float3 bmax(-FLT_MAX);
for (size_t i = 0; i < count; ++i) {
+7 -7
View File
@@ -181,14 +181,14 @@ public:
*
* @return A pointer to the Engine instance this Renderer is associated to.
*/
Engine* UTILS_NONNULL getEngine() noexcept;
Engine* getEngine() noexcept;
/**
* Get the Engine that created this Renderer.
*
* @return A constant pointer to the Engine instance this Renderer is associated to.
*/
inline Engine const* UTILS_NONNULL getEngine() const noexcept {
inline Engine const* getEngine() const noexcept {
return const_cast<Renderer *>(this)->getEngine();
}
@@ -264,7 +264,7 @@ public:
* @see
* endFrame()
*/
bool beginFrame(SwapChain* UTILS_NONNULL swapChain,
bool beginFrame(SwapChain* swapChain,
uint64_t vsyncSteadyClockTimeNano = 0u);
/**
@@ -335,7 +335,7 @@ public:
* beginFrame(), endFrame(), View
*
*/
void render(View const* UTILS_NONNULL view);
void render(View const* view);
/**
* Copy the currently rendered view to the indicated swap chain, using the
@@ -350,7 +350,7 @@ public:
* copyFrame() should be called after a frame is rendered using render()
* but before endFrame() is called.
*/
void copyFrame(SwapChain* UTILS_NONNULL dstSwapChain, Viewport const& dstViewport,
void copyFrame(SwapChain* dstSwapChain, Viewport const& dstViewport,
Viewport const& srcViewport, uint32_t flags = 0);
/**
@@ -490,7 +490,7 @@ public:
* readPixels() is intended for debugging and testing. It will impact performance significantly.
*
*/
void readPixels(RenderTarget* UTILS_NONNULL renderTarget,
void readPixels(RenderTarget* renderTarget,
uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
backend::PixelBufferDescriptor&& buffer);
@@ -517,7 +517,7 @@ public:
* However, internally, renderStandaloneView() is highly multi-threaded to both improve
* performance in mitigate the call's latency.
*/
void renderStandaloneView(View const* UTILS_NONNULL view);
void renderStandaloneView(View const* view);
/**
+6 -6
View File
@@ -75,14 +75,14 @@ public:
*
* @param skybox The Skybox to use to fill untouched pixels, or nullptr to unset the Skybox.
*/
void setSkybox(Skybox* UTILS_NULLABLE skybox) noexcept;
void setSkybox(Skybox* skybox) noexcept;
/**
* Returns the Skybox associated with the Scene.
*
* @return The associated Skybox, or nullptr if there is none.
*/
Skybox* UTILS_NULLABLE getSkybox() const noexcept;
Skybox* getSkybox() const noexcept;
/**
* Set the IndirectLight to use when rendering the Scene.
@@ -93,7 +93,7 @@ public:
* @param ibl The IndirectLight to use when rendering the Scene or nullptr to unset.
* @see getIndirectLight
*/
void setIndirectLight(IndirectLight* UTILS_NULLABLE ibl) noexcept;
void setIndirectLight(IndirectLight* ibl) noexcept;
/**
* Get the IndirectLight or nullptr if none is set.
@@ -101,7 +101,7 @@ public:
* @return the the IndirectLight or nullptr if none is set
* @see setIndirectLight
*/
IndirectLight* UTILS_NULLABLE getIndirectLight() const noexcept;
IndirectLight* getIndirectLight() const noexcept;
/**
* Adds an Entity to the Scene.
@@ -120,7 +120,7 @@ public:
* @param entities Array containing entities to add to the scene.
* @param count Size of the entity array.
*/
void addEntities(const utils::Entity* UTILS_NONNULL entities, size_t count);
void addEntities(const utils::Entity* entities, size_t count);
/**
* Removes the Renderable from the Scene.
@@ -139,7 +139,7 @@ public:
* @param entities Array containing entities to remove from the scene.
* @param count Size of the entity array.
*/
void removeEntities(const utils::Entity* UTILS_NONNULL entities, size_t count);
void removeEntities(const utils::Entity* entities, size_t count);
/**
* Returns the total number of Entities in the Scene, whether alive or not.
+5 -4
View File
@@ -74,7 +74,8 @@ public:
*
* @param engine Reference to the filament::Engine to associate this SkinningBuffer with.
*
* @return pointer to the newly created object.
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
*
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
* memory or other resources.
@@ -82,7 +83,7 @@ public:
*
* @see SkinningBuffer::setBones
*/
SkinningBuffer* UTILS_NONNULL build(Engine& engine);
SkinningBuffer* build(Engine& engine);
private:
friend class FSkinningBuffer;
};
@@ -95,7 +96,7 @@ public:
* @param offset offset in elements (not bytes) in the SkinningBuffer (not in transforms)
* @see RenderableManager::setSkinningBuffer
*/
void setBones(Engine& engine, RenderableManager::Bone const* UTILS_NONNULL transforms,
void setBones(Engine& engine, RenderableManager::Bone const* transforms,
size_t count, size_t offset = 0);
/**
@@ -106,7 +107,7 @@ public:
* @param offset offset in elements (not bytes) in the SkinningBuffer (not in transforms)
* @see RenderableManager::setSkinningBuffer
*/
void setBones(Engine& engine, math::mat4f const* UTILS_NONNULL transforms,
void setBones(Engine& engine, math::mat4f const* transforms,
size_t count, size_t offset = 0);
/**
+5 -5
View File
@@ -92,7 +92,7 @@ public:
*
* @see Texture
*/
Builder& environment(Texture* UTILS_NONNULL cubemap) noexcept;
Builder& environment(Texture* cubemap) noexcept;
/**
* Indicates whether the sun should be rendered. The sun can only be
@@ -136,9 +136,9 @@ public:
*
* @param engine Reference to the filament::Engine to associate this Skybox with.
*
* @return pointer to the newly created object.
* @return pointer to the newly created object, or nullptr if the light couldn't be created.
*/
Skybox* UTILS_NONNULL build(Engine& engine);
Skybox* build(Engine& engine);
private:
friend class FSkybox;
@@ -172,9 +172,9 @@ public:
float getIntensity() const noexcept;
/**
* @return the associated texture
* @return the associated texture, or null if it does not exist
*/
Texture const* UTILS_NONNULL getTexture() const noexcept;
Texture const* getTexture() const noexcept;
protected:
// prevent heap allocation
+6 -9
View File
@@ -114,7 +114,7 @@ public:
*
* @return This Builder, for chaining calls.
*/
Builder& stream(void* UTILS_NULLABLE stream) noexcept;
Builder& stream(void* stream) noexcept;
/**
*
@@ -141,9 +141,9 @@ public:
*
* @param engine Reference to the filament::Engine to associate this Stream with.
*
* @return pointer to the newly created object.
* @return pointer to the newly created object, or nullptr if the stream couldn't be created.
*/
Stream* UTILS_NONNULL build(Engine& engine);
Stream* build(Engine& engine);
private:
friend class FStream;
@@ -171,12 +171,11 @@ public:
*
* @param image Pointer to AHardwareBuffer, casted to void* since this is a public header.
* @param callback This is triggered by Filament when it wishes to release the image.
* The callback tales two arguments: the AHardwareBuffer and the userdata.
* It callback tales two arguments: the AHardwareBuffer and the userdata.
* @param userdata Optional closure data. Filament will pass this into the callback when it
* releases the image.
*/
void setAcquiredImage(void* UTILS_NONNULL image,
Callback UTILS_NONNULL callback, void* UTILS_NULLABLE userdata) noexcept;
void setAcquiredImage(void* image, Callback callback, void* userdata) noexcept;
/**
* @see setAcquiredImage(void*, Callback, void*)
@@ -188,9 +187,7 @@ public:
* @param userdata Optional closure data. Filament will pass this into the callback when it
* releases the image.
*/
void setAcquiredImage(void* UTILS_NONNULL image,
backend::CallbackHandler* UTILS_NULLABLE handler,
Callback UTILS_NONNULL callback, void* UTILS_NULLABLE userdata) noexcept;
void setAcquiredImage(void* image, backend::CallbackHandler* handler, Callback callback, void* userdata) noexcept;
/**
* Updates the size of the incoming stream. Whether this value is used is
+4 -5
View File
@@ -152,7 +152,7 @@ class Engine;
class UTILS_PUBLIC SwapChain : public FilamentAPI {
public:
using FrameScheduledCallback = backend::FrameScheduledCallback;
using FrameCompletedCallback = utils::Invocable<void(SwapChain* UTILS_NONNULL)>;
using FrameCompletedCallback = utils::Invocable<void(SwapChain*)>;
/**
* Requests a SwapChain with an alpha channel.
@@ -236,7 +236,7 @@ public:
*/
static bool isSRGBSwapChainSupported(Engine& engine) noexcept;
void* UTILS_NULLABLE getNativeWindow() const noexcept;
void* getNativeWindow() const noexcept;
/**
* FrameScheduledCallback is a callback function that notifies an application when Filament has
@@ -269,8 +269,7 @@ public:
*
* @see PresentCallable
*/
void setFrameScheduledCallback(FrameScheduledCallback UTILS_NULLABLE callback,
void* UTILS_NULLABLE user = nullptr);
void setFrameScheduledCallback(FrameScheduledCallback callback, void* user = nullptr);
/**
* FrameCompletedCallback is a callback function that notifies an application when a frame's
@@ -291,7 +290,7 @@ public:
*
* @see CallbackHandler
*/
void setFrameCompletedCallback(backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
void setFrameCompletedCallback(backend::CallbackHandler* handler = nullptr,
FrameCompletedCallback&& callback = {}) noexcept;
+7 -6
View File
@@ -204,13 +204,14 @@ public:
*
* @param engine Reference to the filament::Engine to associate this Texture with.
*
* @return pointer to the newly created object.
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
*
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
* memory or other resources.
* @exception utils::PreConditionPanic if a parameter to a builder function was invalid.
*/
Texture* UTILS_NONNULL build(Engine& engine);
Texture* build(Engine& engine);
/* no user serviceable parts below */
@@ -399,7 +400,7 @@ public:
* @see Builder::sampler()
*
*/
void setExternalImage(Engine& engine, void* UTILS_NONNULL image) noexcept;
void setExternalImage(Engine& engine, void* image) noexcept;
/**
* Specify the external image and plane to associate with this Texture. Typically the external
@@ -430,7 +431,7 @@ public:
* kCVPixelFormatType_420YpCbCr8BiPlanarFullRange images. On platforms
* other than iOS, this method is a no-op.
*/
void setExternalImage(Engine& engine, void* UTILS_NONNULL image, size_t plane) noexcept;
void setExternalImage(Engine& engine, void* image, size_t plane) noexcept;
/**
* Specify the external stream to associate with this Texture. Typically the external
@@ -449,7 +450,7 @@ public:
* @see Builder::sampler(), Stream
*
*/
void setExternalStream(Engine& engine, Stream* UTILS_NULLABLE stream) noexcept;
void setExternalStream(Engine& engine, Stream* stream) noexcept;
/**
* Generates all the mipmap levels automatically. This requires the texture to have a
@@ -499,7 +500,7 @@ public:
*/
void generatePrefilterMipmap(Engine& engine,
PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets,
PrefilterOptions const* UTILS_NULLABLE options = nullptr);
PrefilterOptions const* options = nullptr);
/** @deprecated */
+2 -2
View File
@@ -140,7 +140,7 @@ public:
* Retrieve the Entities of all the components of this manager.
* @return A list, in no particular order, of all the entities managed by this manager.
*/
utils::Entity const* UTILS_NONNULL getEntities() const noexcept;
utils::Entity const* getEntities() const noexcept;
/**
* Enables or disable the accurate translation mode. Disabled by default.
@@ -224,7 +224,7 @@ public:
* @param count The maximum number of children to retrieve.
* @return The number of children written to the pointer.
*/
size_t getChildren(Instance i, utils::Entity* UTILS_NONNULL children, size_t count) const noexcept;
size_t getChildren(Instance i, utils::Entity* children, size_t count) const noexcept;
/**
* Returns an iterator to the Instance of the first child of the given parent.
+4 -4
View File
@@ -163,13 +163,14 @@ public:
*
* @param engine Reference to the filament::Engine to associate this VertexBuffer with.
*
* @return pointer to the newly created object.
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
*
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
* memory or other resources.
* @exception utils::PreConditionPanic if a parameter to a builder function was invalid.
*/
VertexBuffer* UTILS_NONNULL build(Engine& engine);
VertexBuffer* build(Engine& engine);
private:
friend class FVertexBuffer;
@@ -208,8 +209,7 @@ public:
* and Builder::bufferCount() - 1.
* @param bufferObject The handle to the GPU data that will be used in this buffer slot.
*/
void setBufferObjectAt(Engine& engine, uint8_t bufferIndex,
BufferObject const* UTILS_NONNULL bufferObject);
void setBufferObjectAt(Engine& engine, uint8_t bufferIndex, BufferObject const* bufferObject);
protected:
// prevent heap allocation
+20 -22
View File
@@ -93,7 +93,7 @@ public:
* Sets the View's name. Only useful for debugging.
* @param name Pointer to the View's name. The string is copied.
*/
void setName(const char* UTILS_NONNULL name) noexcept;
void setName(const char* name) noexcept;
/**
* Returns the View's name
@@ -102,7 +102,7 @@ public:
*
* @attention Do *not* free the pointer or modify its content.
*/
const char* UTILS_NULLABLE getName() const noexcept;
const char* getName() const noexcept;
/**
* Set this View instance's Scene.
@@ -118,19 +118,19 @@ public:
* There is no reference-counting.
* Make sure to dissociate a Scene from all Views before destroying it.
*/
void setScene(Scene* UTILS_NULLABLE scene);
void setScene(Scene* scene);
/**
* Returns the Scene currently associated with this View.
* @return A pointer to the Scene associated to this View. nullptr if no Scene is set.
*/
Scene* UTILS_NULLABLE getScene() noexcept;
Scene* getScene() noexcept;
/**
* Returns the Scene currently associated with this View.
* @return A pointer to the Scene associated to this View. nullptr if no Scene is set.
*/
Scene const* UTILS_NULLABLE getScene() const noexcept {
Scene const* getScene() const noexcept {
return const_cast<View*>(this)->getScene();
}
@@ -145,7 +145,7 @@ public:
*
* @param renderTarget Render target associated with view, or nullptr for the swap chain.
*/
void setRenderTarget(RenderTarget* UTILS_NULLABLE renderTarget) noexcept;
void setRenderTarget(RenderTarget* renderTarget) noexcept;
/**
* Gets the offscreen render target associated with this view.
@@ -154,7 +154,7 @@ public:
*
* @see setRenderTarget
*/
RenderTarget* UTILS_NULLABLE getRenderTarget() const noexcept;
RenderTarget* getRenderTarget() const noexcept;
/**
* Sets the rectangular region to render to.
@@ -187,7 +187,7 @@ public:
* There is no reference-counting.
* Make sure to dissociate a Camera from all Views before destroying it.
*/
void setCamera(Camera* UTILS_NONNULL camera) noexcept;
void setCamera(Camera* camera) noexcept;
/**
* Returns the Camera currently associated with this View.
@@ -404,13 +404,13 @@ public:
* There is no reference-counting.
* Make sure to dissociate a ColorGrading from all Views before destroying it.
*/
void setColorGrading(ColorGrading* UTILS_NULLABLE colorGrading) noexcept;
void setColorGrading(ColorGrading* colorGrading) noexcept;
/**
* Returns the color grading transforms currently associated to this view.
* @return A pointer to the ColorGrading associated to this View.
*/
const ColorGrading* UTILS_NULLABLE getColorGrading() const noexcept;
const ColorGrading* getColorGrading() const noexcept;
/**
* Sets ambient occlusion options.
@@ -716,10 +716,10 @@ public:
bool isFrustumCullingEnabled() const noexcept;
//! debugging: sets the Camera used for rendering. It may be different from the culling camera.
void setDebugCamera(Camera* UTILS_NULLABLE camera) noexcept;
void setDebugCamera(Camera* camera) noexcept;
//! debugging: returns a Camera from the point of view of *the* dominant directional light used for shadowing.
Camera const* UTILS_NULLABLE getDirectionalLightCamera() const noexcept;
Camera const* getDirectionalLightCamera() const noexcept;
/** Result of a picking query */
@@ -748,12 +748,11 @@ public:
/** User data for PickingQueryResultCallback */
struct PickingQuery {
// note: this is enough to store a std::function<> -- just saying...
void* UTILS_NULLABLE storage[4];
void* storage[4];
};
/** callback type used for picking queries. */
using PickingQueryResultCallback =
void(*)(PickingQueryResult const& result, PickingQuery* UTILS_NONNULL pq);
using PickingQueryResultCallback = void(*)(PickingQueryResult const& result, PickingQuery* pq);
/**
* Helper for creating a picking query from Foo::method, by pointer.
@@ -767,8 +766,8 @@ public:
* @param handler Handler to dispatch the callback or nullptr for the default handler.
*/
template<typename T, void(T::*method)(PickingQueryResult const&)>
void pick(uint32_t x, uint32_t y, T* UTILS_NONNULL instance,
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr) noexcept {
void pick(uint32_t x, uint32_t y, T* instance,
backend::CallbackHandler* handler = nullptr) noexcept {
PickingQuery& query = pick(x, y, [](PickingQueryResult const& result, PickingQuery* pq) {
(static_cast<T*>(pq->storage[0])->*method)(result);
}, handler);
@@ -788,7 +787,7 @@ public:
*/
template<typename T, void(T::*method)(PickingQueryResult const&)>
void pick(uint32_t x, uint32_t y, T instance,
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr) noexcept {
backend::CallbackHandler* handler = nullptr) noexcept {
static_assert(sizeof(instance) <= sizeof(PickingQuery::storage), "user data too large");
PickingQuery& query = pick(x, y, [](PickingQueryResult const& result, PickingQuery* pq) {
T* const that = static_cast<T*>(reinterpret_cast<void*>(pq->storage));
@@ -809,7 +808,7 @@ public:
*/
template<typename T>
void pick(uint32_t x, uint32_t y, T functor,
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr) noexcept {
backend::CallbackHandler* handler = nullptr) noexcept {
static_assert(sizeof(functor) <= sizeof(PickingQuery::storage), "functor too large");
PickingQuery& query = pick(x, y, handler,
(PickingQueryResultCallback)[](PickingQueryResult const& result, PickingQuery* pq) {
@@ -835,9 +834,8 @@ public:
* 8*sizeof(void*) bytes of user data. This user data is later accessible
* in the PickingQueryResultCallback callback 3rd parameter.
*/
PickingQuery& pick(uint32_t x, uint32_t y,
backend::CallbackHandler* UTILS_NULLABLE handler,
PickingQueryResultCallback UTILS_NONNULL callback) noexcept;
PickingQuery& pick(uint32_t x, uint32_t y, backend::CallbackHandler* handler,
PickingQueryResultCallback callback) noexcept;
/**
* Set the value of material global variables. There are up-to four such variable each of
+1 -1
View File
@@ -25,7 +25,7 @@ MaterialInstance* Material::createInstance(const char* name) const noexcept {
}
const char* Material::getName() const noexcept {
return downcast(this)->getName().c_str_safe();
return downcast(this)->getName().c_str();
}
Shading Material::getShading() const noexcept {
+15 -31
View File
@@ -16,30 +16,15 @@
#include "ResourceAllocator.h"
#include <filament/Engine.h>
#include "private/backend/DriverApi.h"
#include "details/Texture.h"
#include <backend/DriverApiForward.h>
#include <backend/Handle.h>
#include <backend/TargetBufferInfo.h>
#include <backend/DriverEnums.h>
#include "private/backend/DriverApi.h"
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/FixedCapacityVector.h>
#include <utils/Log.h>
#include <utils/ostream.h>
#include <utils/debug.h>
#include <array>
#include <algorithm>
#include <iterator>
#include <utility>
#include <stddef.h>
#include <stdint.h>
using namespace utils;
@@ -57,7 +42,8 @@ ResourceAllocator::AssociativeContainer<K, V, H>::AssociativeContainer() {
template<typename K, typename V, typename H>
UTILS_NOINLINE
ResourceAllocator::AssociativeContainer<K, V, H>::~AssociativeContainer() noexcept = default;
ResourceAllocator::AssociativeContainer<K, V, H>::~AssociativeContainer() noexcept {
}
template<typename K, typename V, typename H>
UTILS_NOINLINE
@@ -92,9 +78,9 @@ void ResourceAllocator::AssociativeContainer<K, V, H>::emplace(ARGS&& ... args)
ResourceAllocatorInterface::~ResourceAllocatorInterface() = default;
size_t ResourceAllocator::TextureKey::getSize() const noexcept {
size_t const pixelCount = width * height * depth;
size_t pixelCount = width * height * depth;
size_t size = pixelCount * FTexture::getFormatSize(format);
size_t const s = std::max(uint8_t(1), samples);
size_t s = std::max(uint8_t(1), samples);
if (s > 1) {
// if we have MSAA, we assume N times the storage
size *= s;
@@ -108,10 +94,8 @@ size_t ResourceAllocator::TextureKey::getSize() const noexcept {
return size;
}
ResourceAllocator::ResourceAllocator(Engine::Config const& config, DriverApi& driverApi) noexcept
: mCacheCapacity(config.resourceAllocatorCacheSizeMB << 20),
mCacheMaxAge(config.resourceAllocatorCacheMaxAge),
mBackend(driverApi) {
ResourceAllocator::ResourceAllocator(DriverApi& driverApi) noexcept
: mBackend(driverApi) {
}
ResourceAllocator::~ResourceAllocator() noexcept {
@@ -128,7 +112,7 @@ void ResourceAllocator::terminate() noexcept {
}
}
RenderTargetHandle ResourceAllocator::createRenderTarget(const char*,
RenderTargetHandle ResourceAllocator::createRenderTarget(const char* name,
TargetBufferFlags targetBufferFlags, uint32_t width, uint32_t height,
uint8_t samples, MRT color, TargetBufferInfo depth,
TargetBufferInfo stencil) noexcept {
@@ -197,7 +181,7 @@ void ResourceAllocator::destroyTexture(TextureHandle h) noexcept {
// move it to the cache
const TextureKey key = it->second;
uint32_t const size = key.getSize();
uint32_t size = key.getSize();
mTextureCache.emplace(key, TextureCachePayload{ h, mAge, size });
mCacheSize += size;
@@ -224,9 +208,9 @@ void ResourceAllocator::gc() noexcept {
auto& textureCache = mTextureCache;
for (auto it = textureCache.begin(); it != textureCache.end();) {
const size_t ageDiff = age - it->second.age;
if (ageDiff >= mCacheMaxAge) {
if (ageDiff >= CACHE_MAX_AGE) {
it = purge(it);
if (mCacheSize < mCacheCapacity) {
if (mCacheSize < CACHE_CAPACITY) {
// if we're not at capacity, only purge a single entry per gc, trying to
// avoid a burst of work.
break;
@@ -236,7 +220,7 @@ void ResourceAllocator::gc() noexcept {
}
}
if (UTILS_UNLIKELY(mCacheSize >= mCacheCapacity)) {
if (UTILS_UNLIKELY(mCacheSize >= CACHE_CAPACITY)) {
// make a copy of our CacheContainer to a vector
using Vector = FixedCapacityVector<std::pair<TextureKey, TextureCachePayload>>;
auto cache = Vector::with_capacity(textureCache.size());
@@ -249,14 +233,14 @@ void ResourceAllocator::gc() noexcept {
// now remove entries until we're at capacity
auto curr = cache.begin();
while (mCacheSize >= mCacheCapacity) {
while (mCacheSize >= CACHE_CAPACITY) {
// by construction this entry must exist
purge(textureCache.find(curr->first));
++curr;
}
// Since we're sorted already, reset the oldestAge of the whole system
size_t const oldestAge = cache.front().second.age;
size_t oldestAge = cache.front().second.age;
for (auto& it : textureCache) {
it.second.age -= oldestAge;
}
+4 -8
View File
@@ -17,8 +17,6 @@
#ifndef TNT_FILAMENT_RESOURCEALLOCATOR_H
#define TNT_FILAMENT_RESOURCEALLOCATOR_H
#include <filament/Engine.h>
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include <backend/TargetBufferInfo.h>
@@ -29,9 +27,7 @@
#include <array>
#include <vector>
#include <utility>
#include <stddef.h>
#include <stdint.h>
namespace filament {
@@ -66,8 +62,7 @@ protected:
class ResourceAllocator final : public ResourceAllocatorInterface {
public:
explicit ResourceAllocator(
Engine::Config const& config, backend::DriverApi& driverApi) noexcept;
explicit ResourceAllocator(backend::DriverApi& driverApi) noexcept;
~ResourceAllocator() noexcept override;
void terminate() noexcept;
@@ -94,8 +89,9 @@ public:
void gc() noexcept;
private:
size_t const mCacheCapacity;
size_t const mCacheMaxAge;
// TODO: these should be settings of the engine
static constexpr size_t CACHE_CAPACITY = 64u << 20u; // 64 MiB
static constexpr size_t CACHE_MAX_AGE = 30u;
struct TextureKey {
const char* name; // doesn't participate in the hash
+1 -1
View File
@@ -163,7 +163,7 @@ public:
FCamera const& getCamera() const noexcept { return *mCamera; }
// use only for debugging
FCamera const* getDebugCamera() const noexcept { return mDebugCamera; }
FCamera const& getDebugCamera() const noexcept { return *mDebugCamera; }
// Update SceneInfo struct for a given light
static void updateSceneInfoDirectional(const math::mat4f& Mv, FScene const& scene,
+1 -1
View File
@@ -100,7 +100,7 @@ public:
// for debugging only
FCamera const* getDirectionalLightCamera() const noexcept {
return getShadowMap(0).getDebugCamera();
return &getShadowMap(0).getDebugCamera();
}
private:
+1 -2
View File
@@ -28,8 +28,7 @@ void Stream::setAcquiredImage(void* image, Callback callback, void* userdata) no
downcast(this)->setAcquiredImage(image, callback, userdata);
}
void Stream::setAcquiredImage(void* image,
backend::CallbackHandler* handler, Callback callback, void* userdata) noexcept {
void Stream::setAcquiredImage(void* image, backend::CallbackHandler* handler, Callback callback, void* userdata) noexcept {
downcast(this)->setAcquiredImage(image, handler, callback, userdata);
}
-4
View File
@@ -34,10 +34,6 @@ class FEngine;
class FDebugRegistry : public DebugRegistry {
public:
enum Type {
BOOL, INT, FLOAT, FLOAT2, FLOAT3, FLOAT4
};
FDebugRegistry() noexcept;
void registerProperty(std::string_view name, bool* p) noexcept {
+8 -10
View File
@@ -252,7 +252,7 @@ void FEngine::init() {
slog.i << "FEngine feature level: " << int(mActiveFeatureLevel) << io::endl;
mResourceAllocator = new ResourceAllocator(mConfig, driverApi);
mResourceAllocator = new ResourceAllocator(driverApi);
mFullScreenTriangleVb = downcast(VertexBuffer::Builder()
.vertexCount(3)
@@ -709,9 +709,7 @@ const FMaterial* FEngine::getSkyboxMaterial() const noexcept {
template<typename T>
inline T* FEngine::create(ResourceList<T>& list, typename T::Builder const& builder) noexcept {
T* p = mHeapAllocator.make<T>(*this, builder);
if (UTILS_UNLIKELY(p)) { // this should never happen
list.insert(p);
}
list.insert(p);
return p;
}
@@ -773,7 +771,7 @@ FRenderTarget* FEngine::createRenderTarget(const RenderTarget::Builder& builder)
FRenderer* FEngine::createRenderer() noexcept {
FRenderer* p = mHeapAllocator.make<FRenderer>(*this);
if (UTILS_UNLIKELY(p)) { // should never happen
if (p) {
mRenderers.insert(p);
}
return p;
@@ -782,7 +780,7 @@ FRenderer* FEngine::createRenderer() noexcept {
FMaterialInstance* FEngine::createMaterialInstance(const FMaterial* material,
const FMaterialInstance* other, const char* name) noexcept {
FMaterialInstance* p = mHeapAllocator.make<FMaterialInstance>(*this, other, name);
if (UTILS_UNLIKELY(p)) { // should never happen
if (p) {
auto pos = mMaterialInstances.emplace(material, "MaterialInstance");
pos.first->second.insert(p);
}
@@ -795,7 +793,7 @@ FMaterialInstance* FEngine::createMaterialInstance(const FMaterial* material,
FScene* FEngine::createScene() noexcept {
FScene* p = mHeapAllocator.make<FScene>(*this);
if (UTILS_UNLIKELY(p)) { // should never happen
if (p) {
mScenes.insert(p);
}
return p;
@@ -803,7 +801,7 @@ FScene* FEngine::createScene() noexcept {
FView* FEngine::createView() noexcept {
FView* p = mHeapAllocator.make<FView>(*this);
if (UTILS_UNLIKELY(p)) { // should never happen
if (p) {
mViews.insert(p);
}
return p;
@@ -811,7 +809,7 @@ FView* FEngine::createView() noexcept {
FFence* FEngine::createFence() noexcept {
FFence* p = mHeapAllocator.make<FFence>(*this);
if (UTILS_UNLIKELY(p)) { // should never happen
if (p) {
std::lock_guard const guard(mFenceListLock);
mFences.insert(p);
}
@@ -827,7 +825,7 @@ FSwapChain* FEngine::createSwapChain(void* nativeWindow, uint64_t flags) noexcep
getDriverApi().setupExternalImage(nativeWindow);
}
FSwapChain* p = mHeapAllocator.make<FSwapChain>(*this, nativeWindow, flags);
if (UTILS_UNLIKELY(p)) { // should never happen
if (p) {
mSwapChains.insert(p);
}
return p;
+1 -1
View File
@@ -269,7 +269,7 @@ const char* FMaterialInstance::getName() const noexcept {
// the instance's CString rather than calling empty(). This allows instances to override the
// parent material's name with a blank string.
if (mName.data() == nullptr) {
return mMaterial->getName().c_str_safe();
return mMaterial->getName().c_str();
}
return mName.c_str();
}
+2 -4
View File
@@ -86,13 +86,11 @@ void FStream::terminate(FEngine& engine) noexcept {
engine.getDriverApi().destroyStream(mStreamHandle);
}
void FStream::setAcquiredImage(void* image,
Callback callback, void* userdata) noexcept {
void FStream::setAcquiredImage(void* image, Callback callback, void* userdata) noexcept {
mEngine.getDriverApi().setAcquiredImage(mStreamHandle, image, nullptr, callback, userdata);
}
void FStream::setAcquiredImage(void* image,
CallbackHandler* handler, Callback callback, void* userdata) noexcept {
void FStream::setAcquiredImage(void* image, CallbackHandler* handler, Callback callback, void* userdata) noexcept {
mEngine.getDriverApi().setAcquiredImage(mStreamHandle, image, handler, callback, userdata);
}
+1 -1
View File
@@ -490,7 +490,7 @@ private:
FScene* mScene = nullptr;
// The camera set by the user, used for culling and viewing
FCamera* /* UTILS_NONNULL */ mCullingCamera = nullptr; // FIXME: should alaways be non-null
FCamera* mCullingCamera = nullptr;
// The optional (debug) camera, used only for viewing
FCamera* mViewingCamera = nullptr;
+2 -2
View File
@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
spec.version = "1.50.3"
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.3/filament-v1.50.3-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();
}
+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) {
-8
View File
@@ -179,14 +179,6 @@
# define UTILS_HAS_FEATURE_CXX_THREAD_LOCAL 0
#endif
#if defined(__clang__)
#define UTILS_NONNULL _Nonnull
#define UTILS_NULLABLE _Nullable
#else
#define UTILS_NONNULL
#define UTILS_NULLABLE
#endif
#if defined(_MSC_VER)
// MSVC does not support loop unrolling hints
# define UTILS_UNROLL
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "filament",
"version": "1.50.3",
"version": "1.50.0",
"description": "Real-time physically based rendering engine",
"main": "filament.js",
"module": "filament.js",