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
18 changed files with 4285 additions and 3 deletions

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))))

View File

@@ -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

108
libs/astrict/CMakeLists.txt Normal file
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)

View File

@@ -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

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

View File

@@ -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

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

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

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

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

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

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

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
libs/astrict/src/ToGlsl.cpp Normal file
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

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();
}

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)

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) {