From 74f2f47cb63b02638270beecd20acea1a0f5665e Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Wed, 27 Sep 2017 11:17:39 -0700 Subject: First attempt at a Linux build (#193) * First attempt at a Linux build - Fix up places where C++ idioms were written assuming lenient behavior of Microsoft's compiler - Add a few more alternatives for platform-specific behavior where Windows was the only platform accounted for. - Add a basic Makefile that can at least invoke our build, even if it isn't going good dependency tracking, etc. - Build `libslang.so` and `slangc` that depends on it, using a relative `RPATH` to make the binary portable (I hope) - Add an initial `.travis.yml` to see if we can trigger their build process. * Fixup: const bug in `List::Sort` I'm not clear why this gets picked up by the gcc *and* clang that Travis uses, but not the (newer) gcc I'm using on Ubuntu here, but I'm hoping it is just some missing `const` qualifiers. * Fixup: reorder specialization of "class info" Clang complains about things being specialized after being instantiated (implicilty), and I hope it is just the fact that I generate the class info for the roots of the hierarchy after the other cases. We'll see. * Fixup: add `platform.cpp` to unified/lumped build * Fixup: Windows uses `FreeLibrary` and not `UnloadLibrary` * Fixup: fix Windows project file to include new source file This obviously points to the fact that we are going to need to be generating these files sooner or later. --- .travis.yml | 20 + Makefile | 116 ++++ slang.h | 33 +- source/core/array-view.h | 2 +- source/core/common.h | 16 +- source/core/core.vcxproj | 1 + source/core/hash.h | 1 + source/core/list.h | 2 +- source/core/platform.cpp | 74 +++ source/core/platform.h | 38 ++ source/core/secure-crt.h | 1 + source/core/slang-string.h | 61 +- source/core/smart-pointer.h | 2 +- source/core/stream.cpp | 2 +- source/core/stream.h | 2 +- source/slang-glslang/slang-glslang.cpp | 2 +- source/slang/bytecode.cpp | 2 +- source/slang/check.cpp | 158 +---- source/slang/compiler.cpp | 117 ++-- source/slang/core.meta.slang.cpp | 916 --------------------------- source/slang/core.meta.slang.h | 916 +++++++++++++++++++++++++++ source/slang/diagnostics.cpp | 2 +- source/slang/emit.cpp | 8 +- source/slang/glsl.meta.slang.cpp | 206 ------ source/slang/glsl.meta.slang.h | 206 ++++++ source/slang/hlsl.meta.slang.cpp | 1089 -------------------------------- source/slang/hlsl.meta.slang.h | 1089 ++++++++++++++++++++++++++++++++ source/slang/ir.h | 2 +- source/slang/lexer.h | 2 +- source/slang/lookup.h | 2 +- source/slang/lower-to-ir.cpp | 9 +- source/slang/lower.cpp | 245 +++---- source/slang/parameter-binding.cpp | 8 +- source/slang/parameter-binding.h | 2 +- source/slang/parser.cpp | 2 +- source/slang/profile.cpp | 2 +- source/slang/reflection.cpp | 40 +- source/slang/slang-stdlib.cpp | 6 +- source/slang/syntax.cpp | 49 +- source/slang/syntax.h | 40 +- source/slang/type-defs.h | 9 +- source/slang/type-layout.cpp | 4 +- source/slang/vm.cpp | 2 +- source/slangc/main.cpp | 4 +- tools/render-test/render-d3d11.cpp | 2 +- tools/slang-generate/main.cpp | 2 +- 46 files changed, 2851 insertions(+), 2663 deletions(-) create mode 100644 .travis.yml create mode 100644 Makefile create mode 100644 source/core/platform.cpp create mode 100644 source/core/platform.h delete mode 100644 source/slang/core.meta.slang.cpp create mode 100644 source/slang/core.meta.slang.h delete mode 100644 source/slang/glsl.meta.slang.cpp create mode 100644 source/slang/glsl.meta.slang.h delete mode 100644 source/slang/hlsl.meta.slang.cpp create mode 100644 source/slang/hlsl.meta.slang.h diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..8084c6bab --- /dev/null +++ b/.travis.yml @@ -0,0 +1,20 @@ +# .travis.yml +# +# This is the configuration file to drive Travis CI for Slang. + +language: cpp + +# Let's test against both major compilers just to be sure. +compiler: + - clang + - gcc + +matrix: + include: + - os: linux + +# Travis wants to default to a build script that invokes +# `./configure && make && make test` which is appropriate +# for autoconf, but I don't want to get into that mess.. +# +script: make && make test diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..138322165 --- /dev/null +++ b/Makefile @@ -0,0 +1,116 @@ +# Makefile +# +# This file provides a simpliistic (perhaps *overly* simplistic) way to +# build Slang from source on Linux, which could probably be adapted for +# building on other Unix-y targets. +# +# This build is not intended to be used for active development right now, +# so it doesn't actually try to compile the `.cpp` files separately, +# or track fine-grained dependencies, so almost any source change will +# trigger a full rebuild. Anybody who wants to do their active development +# on a platform supported by this Makefile should feel free to contribute +# improvements, with the caveat that we will not be adoptttting autoconf, +# CMake, or any other build system that has a tendency to "infect" a codebbbase. +# + +# +# The Windows build (using Visual Studio) tries to output things to +# directories that take the target platform (and build configuration) into +# account. For now we will do something simplistic and request the target +# "triple" from the compiler (which we assume is either gcc or clang) and +# call that our target "platformm" +# +TARGET := $(shell $(CXX) -dumpmachine) + +# +# TODO: We need a way to control the "configuration" (debug vs. release) +# but for now just geting *something* working will be a good start. +# + +# +# We will define an ouput directory for our binaries, based on +# the target platform chosen. If we ever have steps that need to +# output intermediate files, we'd set up the directory here. +# +OUTPUTDIR := bin/$(TARGET)/ +INTERMEDIATEDIR := intermediate/$(TARGET)/ + +# +# Now we will start defining a bunch of variables for build +# options and properties of the target. We are going to unconditionallyy +# set these to what we need/want on our Linux target for now, but +# we will eventually need to do a bit more work to detect the +# platform. +# +SHARED_LIB_PREFIX := lib +SHARED_LIB_SUFFIX := .so +BIN_SUFFIX := +# Note: we set `visibility=hidden` to avoid exporting more symbols than +# we really need. +CFLAGS := -std=c++11 -fvisibility=hidden +LDFLAGS := -L$(OUTPUTDIR) +SHARED_LIB_LDFLAGS := -shared +SHARED_LIB_CFLAGS := -fPIC + +# Make sure that shared library inherits build flags +# from the default case. +SHARED_LIB_LDFLAGS += $(LDFLAGS) +SHARED_LIB_CFLAGS += $(CFLAGS) + +RELATIVE_RPATH_INCANTATION := "-Wl,-rpath,"'$$'"ORIGIN/" + +# TODO: Make sure I'm using these Makefile incantations correctly. +.SUFFIXES: +.PHONY: all clean slang slangc test + +# +# Here we define lists of files (source vs. header dependencies) +# for each logical project we want to build. +# This is the one place where we do any kiind of "dependency" work, +# by making a project depend on the headers for sub-projects it usses. +# +CORE_SOURCES := source/core/*.cpp +CORE_HEADERS := source/core/*.h + +SLANG_SOURCES := source/slang/*.cpp +SLANG_HEADERS := slang.h source/slang/*.h +SLANG_SOURCES += $(CORE_SOURCES) +SLANG_HEADERS += $(CORE_HEADERS) + +SLANGC_SOURCES := source/slangc/*.cpp +SLANGC_HEADERS := $(SLANG_HEADERS) + +# +# Each project will have a variable that is an alias for +# the binary it should produce. +# +SLANG := $(OUTPUTDIR)$(SHARED_LIB_PREFIX)slang$(SHARED_LIB_SUFFIX) +SLANGC := $(OUTPUTDIR)slangc$(BIN_SUFFIX) + +# By default, when the user invokes `make`, we will build the +# `slang` shared library, and the `slangc` front-end application. +all: slang slangc + +mkdirs: $(OUTPUTDIR) + +# Project-specific targets depend on making theappropriate binary. +slang: mkdirs $(SLANG) +slangc: mkdirs $(SLANGC) + + +$(SLANG): $(SLANG_SOURCES) $(SLANG_HEADERS) + $(CXX) $(SHARED_LIB_LDFLAGS) -o $@ -DSLANG_DYNAMIC_EXPORT $(SHARED_LIB_CFLAGS) $(SLANG_SOURCES) + +$(SLANGC): $(SLANGC_SOURCES) $(SLANGC_HEADERS) $(SLANG) + $(CXX) $(LDFLAGS) -o $@ $(CFLAGS) $(SLANGC_SOURCES) $(CORE_SOURCES) -ldl $(RELATIVE_RPATH_INCANTATION) -lslang + + + +$(OUTPUTDIR): + mkdir -p $(OUTPUTDIR) + +test: + # TODO need to actually run the test runner + +clean: + rm -rf $(OUTPUTDIR) diff --git a/slang.h b/slang.h index 7bb50983d..3a09a7cbc 100644 --- a/slang.h +++ b/slang.h @@ -1,17 +1,28 @@ #ifndef SLANG_H #define SLANG_H -#ifdef _MSC_VER -#ifdef SLANG_DYNAMIC_EXPORT -#define SLANG_API __declspec(dllexport) -#else -#ifdef SLANG_DYNAMIC -#define SLANG_API __declspec(dllimport) -#else -#define SLANG_API +#if defined(SLANG_DYNAMIC_EXPORT) + #if !defined(SLANG_DYNAMIC) + #define SLANG_DYNAMIC + #endif #endif + +#if defined(SLANG_DYNAMIC) + #if defined(_MSC_VER) + #ifdef SLANG_DYNAMIC_EXPORT + #define SLANG_API __declspec(dllexport) + #else + #define SLANG_API __declspec(dllimport) + #endif + #else + // TODO: need to consider compiler capabilities +// #ifdef SLANG_DYNAMIC_EXPORT + #define SLANG_API __attribute__((__visibility__("default"))) +// #endif + #endif #endif -#else + +#ifndef SLANG_API #define SLANG_API #endif @@ -19,6 +30,9 @@ #include #endif // ! SLANG_NO_INTTYPES +#ifndef SLANG_NO_STDDEF +#include +#endif // ! SLANG_NO_STDDEF #ifdef __cplusplus extern "C" @@ -1007,6 +1021,7 @@ namespace slang #ifdef SLANG_INCLUDE_IMPLEMENTATION +#include "source/core/platform.cpp" #include "source/core/slang-io.cpp" #include "source/core/slang-string.cpp" #include "source/core/stream.cpp" diff --git a/source/core/array-view.h b/source/core/array-view.h index 4e0057cdb..193aedbbb 100644 --- a/source/core/array-view.h +++ b/source/core/array-view.h @@ -1,7 +1,7 @@ #ifndef CORE_LIB_ARRAY_VIEW_H #define CORE_LIB_ARRAY_VIEW_H -#include "Exception.h" +#include "exception.h" namespace Slang { diff --git a/source/core/common.h b/source/core/common.h index f0f6902d1..dbb837821 100644 --- a/source/core/common.h +++ b/source/core/common.h @@ -13,13 +13,15 @@ namespace Slang { + typedef int32_t Int32; + typedef uint32_t UInt32; + typedef int64_t Int64; - typedef unsigned short Word; -#ifdef _M_X64 - typedef int64_t PtrInt; -#else - typedef int PtrInt; -#endif + typedef uint64_t UInt64; + +// typedef unsigned short Word; + + typedef intptr_t PtrInt; template inline T&& _Move(T & obj) @@ -38,7 +40,7 @@ namespace Slang #ifdef _MSC_VER #define SLANG_RETURN_NEVER __declspec(noreturn) #else -#efine SLANG_RETURN_NEVER /* empty */ +#define SLANG_RETURN_NEVER /* empty */ #endif SLANG_RETURN_NEVER void signalUnexpectedError(char const* message); diff --git a/source/core/core.vcxproj b/source/core/core.vcxproj index 88e776703..ba9fe3d98 100644 --- a/source/core/core.vcxproj +++ b/source/core/core.vcxproj @@ -39,6 +39,7 @@ + diff --git a/source/core/hash.h b/source/core/hash.h index dd2086305..8ee5b088f 100644 --- a/source/core/hash.h +++ b/source/core/hash.h @@ -3,6 +3,7 @@ #include "slang-math.h" #include +#include namespace Slang { diff --git a/source/core/list.h b/source/core/list.h index aeba9557f..af32a39ef 100644 --- a/source/core/list.h +++ b/source/core/list.h @@ -525,7 +525,7 @@ namespace Slang void Sort() { - Sort([](T& t1, T& t2){return t1 + #undef WIN32_LEAN_AND_MEAN + #undef NOMINMAX +#else + #include +#endif + +namespace Slang +{ + // SharedLibrary + + SharedLibrary SharedLibrary::load(char const* name) + { + SharedLibrary result; + result.handle = nullptr; + +#ifdef _WIN32 + { + HMODULE h = LoadLibraryA(name); + result.handle = (Handle) h; + } +#else + { + void* h = dlopen(name, RTLD_LOCAL); + result.handle = (Handle) h; + + } +#endif + + return result; + } + + void SharedLibrary::unload() + { +#ifdef _WIN32 + { + FreeLibrary( + (HMODULE) handle); + } +#else + { + dlclose(handle); + } +#endif + + } + + SharedLibrary::FuncPtr SharedLibrary::findFuncByName(char const* name) + { + FuncPtr funcPtr = nullptr; + +#ifdef _WIN32 + { + funcPtr = (FuncPtr) GetProcAddress( + (HMODULE) handle, + name); + } +#else + { + funcPtr = (FuncPtr) dlsym( + (void*) handle, + name); + } +#endif + + return funcPtr; + } +} \ No newline at end of file diff --git a/source/core/platform.h b/source/core/platform.h new file mode 100644 index 000000000..fef698e6f --- /dev/null +++ b/source/core/platform.h @@ -0,0 +1,38 @@ +// platform.h +#ifndef SLANG_CORE_PLATFORM_H_INCLUDED +#define SLANG_CORE_PLATFORM_H_INCLUDED + +namespace Slang +{ + // Interface for working with shared libraries + // in a platfomr-independent fashion. + struct SharedLibrary + { + typedef struct SharedLibraryImpl* Handle; + Handle handle; + + // Attempt to load a shared library for + // the current platform. + static SharedLibrary load(char const* name); + + // If this refers to a valid loaded library, + // then attempt to unload it + void unload(); + + typedef void (*FuncPtr)(void); + + FuncPtr findFuncByName(char const* name); + + + operator Handle() { return handle; } + }; + +#ifndef _MSC_VER + #define _fileno fileno + #define _isatty isatty + #define _setmode setmode + #define _O_BINARY O_BINARY +#endif +} + +#endif diff --git a/source/core/secure-crt.h b/source/core/secure-crt.h index 12927cc24..a76fb2679 100644 --- a/source/core/secure-crt.h +++ b/source/core/secure-crt.h @@ -2,6 +2,7 @@ #ifndef CORE_LIB_SECURE_CRT_H #define CORE_LIB_SECURE_CRT_H #include +#include #include #include #include diff --git a/source/core/slang-string.h b/source/core/slang-string.h index ed333f8e8..23ab54c23 100644 --- a/source/core/slang-string.h +++ b/source/core/slang-string.h @@ -222,7 +222,7 @@ namespace Slang char* getData() const { - return buffer ? buffer->getData() : ""; + return buffer ? buffer->getData() : (char*)""; } UInt getLength() const @@ -270,50 +270,29 @@ namespace Slang void append(String const& str); void append(StringSlice const& slice); - String(int val, int radix = 10) + String(int32_t val, int radix = 10) { append(val, radix); -#if 0 - buffer = StringRepresentation::createWithLength(33); - buffer->length = IntToAscii(getData(), val, radix); - ReverseInternalAscii(getData(), getLength()); -#endif } - String(unsigned int val, int radix = 10) + String(uint32_t val, int radix = 10) { append(val, radix); -#if 0 - buffer = StringRepresentation::createWithLength(33); - buffer->length = IntToAscii(getData(), val, radix); - ReverseInternalAscii(getData(), getLength()); -#endif } - String(long long val, int radix = 10) + String(int64_t val, int radix = 10) + { + append(val, radix); + } + String(uint64_t val, int radix = 10) { append(val, radix); -#if 0 - buffer = StringRepresentation::createWithLength(65); - buffer->length = IntToAscii(getData(), val, radix); - ReverseInternalAscii(getData(), getLength()); -#endif } String(float val, const char * format = "%g") { append(val, format); -#if 0 - buffer = StringRepresentation::createWithLength(128); - sprintf_s(getData(), 128, format, val); - buffer->length = (int)strnlen_s(begin(), 128); -#endif } String(double val, const char * format = "%g") { append(val, format); -#if 0 - buffer = StringRepresentation::createWithLength(128); - sprintf_s(getData(), 128, format, val); - buffer->length = (int)strnlen_s(begin(), 128); -#endif } String(const char * str) { @@ -656,17 +635,22 @@ namespace Slang Append(&ch, 1); return *this; } - StringBuilder & operator << (int val) + StringBuilder & operator << (Int32 val) + { + Append(val); + return *this; + } + StringBuilder & operator << (UInt32 val) { Append(val); return *this; } - StringBuilder & operator << (unsigned int val) + StringBuilder & operator << (Int64 val) { Append(val); return *this; } - StringBuilder & operator << (long long val) + StringBuilder & operator << (UInt64 val) { Append(val); return *this; @@ -714,21 +698,28 @@ namespace Slang int len = (int)strnlen_s(buf, 128); Append(buf, len); } - void Append(unsigned int value, int radix = 10) + void Append(Int32 value, int radix = 10) { char vBuffer[33]; int len = IntToAscii(vBuffer, value, radix); ReverseInternalAscii(vBuffer, len); Append(vBuffer); } - void Append(int value, int radix = 10) + void Append(UInt32 value, int radix = 10) { char vBuffer[33]; int len = IntToAscii(vBuffer, value, radix); ReverseInternalAscii(vBuffer, len); Append(vBuffer); } - void Append(long long value, int radix = 10) + void Append(Int64 value, int radix = 10) + { + char vBuffer[65]; + int len = IntToAscii(vBuffer, value, radix); + ReverseInternalAscii(vBuffer, len); + Append(vBuffer); + } + void Append(UInt64 value, int radix = 10) { char vBuffer[65]; int len = IntToAscii(vBuffer, value, radix); diff --git a/source/core/smart-pointer.h b/source/core/smart-pointer.h index 3e64eac96..17d6caaa4 100644 --- a/source/core/smart-pointer.h +++ b/source/core/smart-pointer.h @@ -127,7 +127,7 @@ namespace Slang template typename EnableIf::value, void>::type - operator=(RefPtr const& ptr) + operator=(RefPtr const& p) { T* old = pointer; addReference(p.pointer); diff --git a/source/core/stream.cpp b/source/core/stream.cpp index 62e9092af..f78e5af83 100644 --- a/source/core/stream.cpp +++ b/source/core/stream.cpp @@ -1,4 +1,4 @@ -#include "Stream.h" +#include "stream.h" #ifdef _WIN32 #include #endif diff --git a/source/core/stream.h b/source/core/stream.h index 9a8ea8366..4eea6a909 100644 --- a/source/core/stream.h +++ b/source/core/stream.h @@ -1,7 +1,7 @@ #ifndef CORE_LIB_STREAM_H #define CORE_LIB_STREAM_H -#include "Basic.h" +#include "basic.h" namespace Slang { diff --git a/source/slang-glslang/slang-glslang.cpp b/source/slang-glslang/slang-glslang.cpp index 650e58ef6..21a95c3b9 100644 --- a/source/slang-glslang/slang-glslang.cpp +++ b/source/slang-glslang/slang-glslang.cpp @@ -12,7 +12,7 @@ #include "SPIRV/doc.h" #include "SPIRV/disassemble.h" -#include "../../Slang.h" +#include "../../slang.h" #if 0 #include diff --git a/source/slang/bytecode.cpp b/source/slang/bytecode.cpp index 52086c76b..e412a5b94 100644 --- a/source/slang/bytecode.cpp +++ b/source/slang/bytecode.cpp @@ -61,7 +61,7 @@ struct BytecodeGenerationPtr T& operator*() { - return *getPtr() + return *getPtr(); } T& operator[](UInt index) diff --git a/source/slang/check.cpp b/source/slang/check.cpp index e22db4186..5c1f7380c 100644 --- a/source/slang/check.cpp +++ b/source/slang/check.cpp @@ -538,7 +538,7 @@ namespace Slang if (auto basicType = type->As()) { // TODO: `void` shouldn't be a basic type, to make this easier to avoid - if (basicType->BaseType == BaseType::Void) + if (basicType->baseType == BaseType::Void) { // TODO(tfoley): pick the right diagnostic message if (!isRewriteMode()) @@ -723,7 +723,7 @@ namespace Slang // TODO(tfoley): If we can compute the size of the array statically, // then we want to check that there aren't too many initializers present - auto toElementType = toArrayType->BaseType; + auto toElementType = toArrayType->baseType; for(auto& arg : fromInitializerListExpr->args) { @@ -778,123 +778,6 @@ namespace Slang // -#if 0 - if (auto toBasicType = toType->AsBasicType()) - { - if (auto fromBasicType = fromType->AsBasicType()) - { - // Conversions between base types are always allowed, - // and the only question is what the cost will be. - - auto toInfo = GetBaseTypeConversionInfo(toBasicType->BaseType); - auto fromInfo = GetBaseTypeConversionInfo(fromBasicType->BaseType); - - // We expect identical types to have been dealt with already. - SLANG_ASSERT(toInfo.kind != fromInfo.kind || toInfo.rank != fromInfo.rank); - - if (outToExpr) - *outToExpr = CreateImplicitCastExpr(toType, fromExpr); - - - if (outCost) - { - // Conversions within the same kind are easist to handle - if (toInfo.kind == fromInfo.kind) - { - // If we are converting to a "larger" type, then - // we are doing a lossless promotion, and otherwise - // we are doing a demotion. - if( toInfo.rank > fromInfo.rank) - *outCost = kConversionCost_RankPromotion; - else - *outCost = kConversionCost_GeneralConversion; - } - // If we are converting from an unsigned integer type to - // a signed integer type that is guaranteed to be larger, - // then that is also a lossless promotion. - else if(toInfo.kind == kBaseTypeConversionKind_Signed - && fromInfo.kind == kBaseTypeConversionKind_Unsigned - && toInfo.rank > fromInfo.rank) - { - // TODO: probably need to weed out cases involving - // "pointer-sized" integers if these are treated - // as distinct from 32- and 64-bit types. - // E.g., there is no guarantee that conversion - // from 32-bit unsigned to pointer-sized signed - // is lossless, because pointers could be 32-bit, - // and the same applies for conversion from - // `uintptr` to `uint64`. - *outCost = kConversionCost_UnsignedToSignedPromotion; - } - // Conversion from signed to unsigned is always lossy, - // but it is preferred over conversions from unsigned - // to signed, for same-size types. - else if(toInfo.kind == kBaseTypeConversionKind_Unsigned - && fromInfo.kind == kBaseTypeConversionKind_Signed - && toInfo.rank >= fromInfo.rank) - { - *outCost = kConversionCost_SignedToUnsignedConversion; - } - // Conversion from an integer to a floating-point type - // is never considered a promotion (even when the value - // would fit in the available bits). - // If the destination type is at least 32 bits we consider - // this a reasonably good conversion, though. - else if (toInfo.kind == kBaseTypeConversionKind_Float - && toInfo.rank >= kBaseTypeConversionRank_Int32) - { - *outCost = kConversionCost_IntegerToFloatConversion; - } - // All other cases are considered as "general" conversions, - // where we don't consider any one conversion better than - // any others. - else - { - *outCost = kConversionCost_GeneralConversion; - } - } - - return true; - } - } - - if (auto toVectorType = toType->AsVectorType()) - { - if (auto fromVectorType = fromType->AsVectorType()) - { - // Conversion between vector types. - - // If element counts don't match, then bail: - if (!ValuesAreEqual(toVectorType->elementCount, fromVectorType->elementCount)) - return false; - - // Otherwise, if we can convert the element types, we are golden - ConversionCost elementCost; - if (CanCoerce(toVectorType->elementType, fromVectorType->elementType, &elementCost)) - { - if (outToExpr) - *outToExpr = CreateImplicitCastExpr(toType, fromExpr); - if (outCost) - *outCost = elementCost; - return true; - } - } - else if (auto fromScalarType = fromType->AsBasicType()) - { - // Conversion from scalar to vector. - // Should allow as long as we can coerce the scalar to our element type. - ConversionCost elementCost; - if (CanCoerce(toVectorType->elementType, fromScalarType, &elementCost)) - { - if (outToExpr) - *outToExpr = CreateImplicitCastExpr(toType, fromExpr); - if (outCost) - *outCost = elementCost + kConversionCost_ScalarToVector; - return true; - } - } - } -#endif if (auto toDeclRefType = toType->As()) { @@ -1973,7 +1856,7 @@ namespace Slang // Create a new array type based on the size we found, // and install it into our type. varDecl->type.type = getArrayType( - arrayType->BaseType, + arrayType->baseType, elementCount); } @@ -2456,7 +2339,7 @@ namespace Slang { return CheckSimpleSubscriptExpr( subscriptExpr, - baseArrayType->BaseType); + baseArrayType->baseType); } else if (auto vecType = baseType->As()) { @@ -2769,8 +2652,8 @@ namespace Slang { if (auto rightBasic = right->As()) { - auto leftFlavor = leftBasic->BaseType; - auto rightFlavor = rightBasic->BaseType; + auto leftFlavor = leftBasic->baseType; + auto rightFlavor = rightBasic->baseType; // TODO(tfoley): Need a special-case rule here that if // either operand is of type `half`, then we promote @@ -4779,8 +4662,8 @@ namespace Slang auto targetScalarType = targetArithType->GetScalarType(); auto exprScalarType = exprArithType->GetScalarType(); - if (!IsNumeric(exprScalarType->BaseType)) goto fail; - if (!IsNumeric(targetScalarType->BaseType)) goto fail; + if (!IsNumeric(exprScalarType->baseType)) goto fail; + if (!IsNumeric(targetScalarType->baseType)) goto fail; // TODO(tfoley): this checking is incomplete here, and could // lead to downstream compilation failures @@ -4997,6 +4880,19 @@ namespace Slang return expr; } + RefPtr lookupResultFailure( + MemberExpr* expr, + QualType const& baseType) + { + if (!isRewriteMode()) + { + getSink()->diagnose(expr, Diagnostics::noMemberOfNameInType, expr->name, baseType); + } + expr->type = QualType(getSession()->getErrorType()); + return expr; + + } + RefPtr visitMemberExpr(MemberExpr * expr) { expr->BaseExpression = CheckExpr(expr->BaseExpression); @@ -5043,7 +4939,7 @@ namespace Slang this, expr->name, aggTypeDeclRef); if (!lookupResult.isValid()) { - goto fail; + return lookupResultFailure(expr, baseType); } // TODO: need to filter for declarations that are valid to refer @@ -5068,7 +4964,7 @@ namespace Slang this, expr->name, aggTypeDeclRef); if (!lookupResult.isValid()) { - goto fail; + return lookupResultFailure(expr, baseType); } return createLookupResultExpr( @@ -5078,13 +4974,7 @@ namespace Slang } // catch-all - fail: - if (!isRewriteMode()) - { - getSink()->diagnose(expr, Diagnostics::noMemberOfNameInType, expr->name, baseType); - } - expr->type = QualType(getSession()->getErrorType()); - return expr; + return lookupResultFailure(expr, baseType); } // All remaining cases assume we have a `BasicType` else if (!baseType->AsBasicType()) diff --git a/source/slang/compiler.cpp b/source/slang/compiler.cpp index b8830c0b4..d7de5c42e 100644 --- a/source/slang/compiler.cpp +++ b/source/slang/compiler.cpp @@ -1,6 +1,7 @@ // Compiler.cpp : Defines the entry point for the console application. // #include "../core/basic.h" +#include "../core/platform.h" #include "../core/slang-io.h" #include "compiler.h" #include "lexer.h" @@ -12,21 +13,43 @@ #include "reflection.h" #include "emit.h" -// Utilities for pass-through modes -#include "../slang-glslang/slang-glslang.h" +// Enable calling through to `fxc` to +// generate code on Windows. +#ifdef _WIN32 + #define WIN32_LEAN_AND_MEAN + #define NOMINMAX + #include + #undef WIN32_LEAN_AND_MEAN + #undef NOMINMAX + #include + #ifndef SLANG_ENABLE_DXBC_SUPPORT + #define SLANG_ENABLE_DXBC_SUPPORT 1 + #endif +#endif +// +// Otherwise, don't enable DXBC by default: +#ifndef SLANG_ENABLE_DXBC_SUPPORT + #define SLANG_ENABLE_DXBC_SUPPORT 0 +#endif +// Enable calling through to `glslang` on +// all platforms. +#ifndef SLANG_ENABLE_GLSLANG_SUPPORT + #define SLANG_ENABLE_GLSLANG_SUPPORT 1 +#endif -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX -#include -#undef WIN32_LEAN_AND_MEAN -#undef NOMINMAX -#include +#if SLANG_ENABLE_GLSLANG_SUPPORT +#include "../slang-glslang/slang-glslang.h" #endif -#include +// Includes to allow us to control console +// output when writing assembly dumps. #include +#ifdef _WIN32 +#include +#else +#include +#endif #ifdef _MSC_VER #pragma warning(disable: 4996) @@ -189,7 +212,7 @@ namespace Slang } } -#ifdef _WIN32 +#if SLANG_ENABLE_DXBC_SUPPORT HMODULE loadD3DCompilerDLL(CompileRequest* request) { char const* libraryName = "d3dcompiler_47"; @@ -264,28 +287,6 @@ namespace Slang return data; } -#if 0 - List EmitDXBytecode( - ExtraContext& context) - { - if(context.getTranslationUnitOptions().entryPoints.Count() != 1) - { - if(context.getTranslationUnitOptions().entryPoints.Count() == 0) - { - // TODO(tfoley): need to write diagnostics into this whole thing... - fprintf(stderr, "no entry point specified\n"); - } - else - { - fprintf(stderr, "multiple entry points specified\n"); - } - return List(); - } - - return EmitDXBytecodeForEntryPoint(context, context.getTranslationUnitOptions().entryPoints[0]); - } -#endif - String dissassembleDXBC( CompileRequest* compileRequest, void const* data, @@ -345,32 +346,16 @@ namespace Slang return result; } - -#if 0 - String EmitDXBytecodeAssembly( - ExtraContext& context) - { - if(context.getTranslationUnitOptions().entryPoints.Count() == 0) - { - // TODO(tfoley): need to write diagnostics into this whole thing... - fprintf(stderr, "no entry point specified\n"); - return ""; - } - - StringBuilder sb; - for (auto entryPoint : context.getTranslationUnitOptions().entryPoints) - { - sb << EmitDXBytecodeAssemblyForEntryPoint(context, entryPoint); - } - return sb.ProduceString(); - } #endif - HMODULE loadGLSLCompilerDLL(CompileRequest* request) +#if SLANG_ENABLE_GLSLANG_SUPPORT + + SharedLibrary loadGLSLCompilerDLL(CompileRequest* request) { char const* libraryName = "slang-glslang"; // TODO(tfoley): let user specify version of glslang DLL to use. - HMODULE glslCompiler = LoadLibraryA(libraryName); + + SharedLibrary glslCompiler = SharedLibrary::load(libraryName); if (!glslCompiler) { request->mSink.diagnose(SourceLoc(), Diagnostics::failedToLoadDynamicLibrary, libraryName); @@ -378,9 +363,9 @@ namespace Slang return glslCompiler; } - HMODULE getGLSLCompilerDLL(CompileRequest* request) + SharedLibrary getGLSLCompilerDLL(CompileRequest* request) { - static HMODULE glslCompiler = loadGLSLCompilerDLL(request); + static SharedLibrary glslCompiler = loadGLSLCompilerDLL(request); return glslCompiler; } @@ -393,11 +378,11 @@ namespace Slang static glslang_CompileFunc glslang_compile = nullptr; if (!glslang_compile) { - HMODULE glslCompiler = getGLSLCompilerDLL(slangCompileRequest); + SharedLibrary glslCompiler = getGLSLCompilerDLL(slangCompileRequest); if (!glslCompiler) return 1; - glslang_compile = (glslang_CompileFunc)GetProcAddress(glslCompiler, "glslang_compile"); + glslang_compile = (glslang_CompileFunc) glslCompiler.findFuncByName("glslang_compile"); if (!glslang_compile) return 1; } @@ -532,6 +517,7 @@ namespace Slang } break; +#if SLANG_ENABLE_DXBC_SUPPORT case CodeGenTarget::DXBytecode: { List code = EmitDXBytecodeForEntryPoint(entryPoint); @@ -547,6 +533,7 @@ namespace Slang result = CompileResult(code); } break; +#endif case CodeGenTarget::SPIRV: { @@ -712,6 +699,7 @@ namespace Slang switch (compileRequest->Target) { + #if SLANG_ENABLE_DXBC_SUPPORT case CodeGenTarget::DXBytecode: { String assembly = dissassembleDXBC(compileRequest, @@ -720,6 +708,7 @@ namespace Slang writeOutputToConsole(compileRequest, assembly); } break; + #endif case CodeGenTarget::SPIRV: { @@ -738,7 +727,9 @@ namespace Slang else { // Redirecting stdout to a file, so do the usual thing + #ifdef _WIN32 _setmode(stdoutFileDesc, _O_BINARY); + #endif writeOutputFile( compileRequest, stdout, @@ -955,10 +946,6 @@ namespace Slang dumpIntermediateText(compileRequest, data, size, ".spv.asm"); break; - case CodeGenTarget::DXBytecodeAssembly: - dumpIntermediateText(compileRequest, data, size, ".dxbc.asm"); - break; - case CodeGenTarget::SlangIRAssembly: dumpIntermediateText(compileRequest, data, size, ".slang-ir.asm"); break; @@ -971,6 +958,11 @@ namespace Slang } break; + #if SLANG_ENABLE_DXBC_SUPPORT + case CodeGenTarget::DXBytecodeAssembly: + dumpIntermediateText(compileRequest, data, size, ".dxbc.asm"); + break; + case CodeGenTarget::DXBytecode: dumpIntermediateBinary(compileRequest, data, size, ".dxbc"); { @@ -978,6 +970,7 @@ namespace Slang dumpIntermediateText(compileRequest, dxbcAssembly.begin(), dxbcAssembly.Length(), ".dxbc.asm"); } break; + #endif case CodeGenTarget::SlangIR: dumpIntermediateBinary(compileRequest, data, size, ".slang-ir"); diff --git a/source/slang/core.meta.slang.cpp b/source/slang/core.meta.slang.cpp deleted file mode 100644 index cf2052d3c..000000000 --- a/source/slang/core.meta.slang.cpp +++ /dev/null @@ -1,916 +0,0 @@ -sb << "// Slang `core` library\n"; -sb << "\n"; -sb << "// A type that can be used as an operand for builtins\n"; -sb << "interface __BuiltinType {}\n"; -sb << "\n"; -sb << "// A type that can be used for arithmetic operations\n"; -sb << "interface __BuiltinArithmeticType : __BuiltinType {}\n"; -sb << "\n"; -sb << "// A type that logically has a sign (positive/negative/zero)\n"; -sb << "interface __BuiltinSignedArithmeticType : __BuiltinArithmeticType {}\n"; -sb << "\n"; -sb << "// A type that can represent integers\n"; -sb << "interface __BuiltinIntegerType : __BuiltinArithmeticType {}\n"; -sb << "\n"; -sb << "// A type that can represent non-integers\n"; -sb << "interface __BuiltinRealType : __BuiltinArithmeticType {}\n"; -sb << "\n"; -sb << "// A type that uses a floating-point representation\n"; -sb << "interface __BuiltinFloatingPointType : __BuiltinRealType, __BuiltinSignedArithmeticType {}\n"; -sb << "\n"; -sb << "__generic __intrinsic_op(Sequence) U operator,(T left, U right);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op(select) T operator?:(bool condition, T ifTrue, T ifFalse);\n"; -sb << "__generic __intrinsic_op(select) vector operator?:(vector condition, vector ifTrue, vector ifFalse);\n"; -sb << "\n"; -sb << ""; - -// We are going to use code generation to produce the -// declarations for all of our base types. - -static const int kBaseTypeCount = sizeof(kBaseTypes) / sizeof(kBaseTypes[0]); -for (int tt = 0; tt < kBaseTypeCount; ++tt) -{ - EMIT_LINE_DIRECTIVE(); - sb << "__builtin_type(" << int(kBaseTypes[tt].tag) << ") struct " << kBaseTypes[tt].name; - - // Declare interface conformances for this type - - sb << "\n : __BuiltinType\n"; - - switch (kBaseTypes[tt].tag) - { - case BaseType::Float: - sb << "\n , __BuiltinFloatingPointType\n"; - sb << "\n , __BuiltinRealType\n"; - // fall through to: - case BaseType::Int: - sb << "\n , __BuiltinSignedArithmeticType\n"; - // fall through to: - case BaseType::UInt: - case BaseType::UInt64: - sb << "\n , __BuiltinArithmeticType\n"; - // fall through to: - case BaseType::Bool: - sb << "\n , __BuiltinType\n"; - break; - - default: - break; - } - - sb << "\n{\n"; - - - // Declare initializers to convert from various other types - for (int ss = 0; ss < kBaseTypeCount; ++ss) - { - // Don't allow conversion from `void` - if (kBaseTypes[ss].tag == BaseType::Void) - continue; - - // We need to emit a modifier so that the semantic-checking - // layer will know it can use these operations for implicit - // conversion. - ConversionCost conversionCost = getBaseTypeConversionCost( - kBaseTypes[tt], - kBaseTypes[ss]); - - EMIT_LINE_DIRECTIVE(); - sb << "__implicit_conversion(" << conversionCost << ")\n"; - - EMIT_LINE_DIRECTIVE(); - sb << "__init(" << kBaseTypes[ss].name << " value);\n"; - } - - sb << "};\n"; -} - - - -// Declare vector and matrix types - -sb << "__generic __magic_type(Vector) struct vector\n{\n"; -sb << " typedef T Element;\n"; - -// Declare initializer taking a single scalar of the elemnt type -sb << " __implicit_conversion(" << kConversionCost_ScalarToVector << ")\n"; -sb << " __intrinsic_op(" << kIROp_constructVectorFromScalar << ")\n"; -sb << " __init(T value);\n"; - -sb << "};\n"; - -// TODO: Probably need to do similar -sb << "\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__magic_type(Matrix)\n"; -sb << "struct matrix {};\n"; -sb << "\n"; -sb << ""; - - - - -static const struct { - char const* name; - char const* glslPrefix; -} kTypes[] = -{ - {"float", ""}, - {"int", "i"}, - {"uint", "u"}, - {"bool", "b"}, -}; -static const int kTypeCount = sizeof(kTypes) / sizeof(kTypes[0]); - -for (int tt = 0; tt < kTypeCount; ++tt) -{ - // Declare HLSL vector types - for (int ii = 1; ii <= 4; ++ii) - { - sb << "typedef vector<" << kTypes[tt].name << "," << ii << "> " << kTypes[tt].name << ii << ";\n"; - } - - // Declare HLSL matrix types - for (int rr = 2; rr <= 4; ++rr) - for (int cc = 2; cc <= 4; ++cc) - { - sb << "typedef matrix<" << kTypes[tt].name << "," << rr << "," << cc << "> " << kTypes[tt].name << rr << "x" << cc << ";\n"; - } -} - -// Declare additional built-in generic types -// EMIT_LINE_DIRECTIVE(); - - -sb << "__generic\n"; -sb << "__intrinsic_type(" << kIROp_ConstantBufferType << ")\n"; -sb << "__magic_type(ConstantBuffer) struct ConstantBuffer {};\n"; - -sb << "__generic\n"; -sb << "__intrinsic_type(" << kIROp_TextureBufferType << ")\n"; -sb << "__magic_type(TextureBuffer) struct TextureBuffer {};\n"; - - -static const char* kComponentNames[]{ "x", "y", "z", "w" }; -static const char* kVectorNames[]{ "", "x", "xy", "xyz", "xyzw" }; - -// Need to add constructors to the types above -for (int N = 2; N <= 4; ++N) -{ - sb << "__generic __extension vector\n{\n"; - - // initialize from N scalars - sb << "__init("; - for (int ii = 0; ii < N; ++ii) - { - if (ii != 0) sb << ", "; - sb << "T " << kComponentNames[ii]; - } - sb << ");\n"; - - // Initialize from an M-vector and then scalars - for (int M = 2; M < N; ++M) - { - sb << "__init(vector " << kVectorNames[M]; - for (int ii = M; ii < N; ++ii) - { - sb << ", T " << kComponentNames[ii]; - } - sb << ");\n"; - } - - // initialize from another vector of the same size - // - // TODO(tfoley): this overlaps with implicit conversions. - // We should look for a way that we can define implicit - // conversions directly in the stdlib instead... - sb << "__generic __init(vector);\n"; - - // Initialize from two vectors, of size M and N-M - for(int M = 2; M <= (N-2); ++M) - { - int K = N - M; - SLANG_ASSERT(K >= 2); - - sb << "__init(vector " << kVectorNames[M]; - sb << ", vector "; - for (int ii = 0; ii < K; ++ii) - { - sb << kComponentNames[ii]; - } - sb << ");\n"; - } - - sb << "}\n"; -} - -// The above extension was generic in the *type* of the vector, -// but explicit in the *size*. We will now declare an extension -// for each builtin type that is generic in the size. -// -for (int tt = 0; tt < kBaseTypeCount; ++tt) -{ - if(kBaseTypes[tt].tag == BaseType::Void) continue; - - sb << "__generic __extension vector<" - << kBaseTypes[tt].name << ",N>\n{\n"; - - for (int ff = 0; ff < kBaseTypeCount; ++ff) - { - if(kBaseTypes[ff].tag == BaseType::Void) continue; - - // We need a constructor to make a vector from a scalar - // of another type. - - if( tt != ff ) - { - auto cost = getBaseTypeConversionCost( - kBaseTypes[tt], - kBaseTypes[ff]); - cost += kConversionCost_ScalarToVector; - - sb << " __implicit_conversion(" << cost << ")\n"; - sb << " __init(" << kBaseTypes[ff].name << " value);\n"; - } - } - - sb << "}\n"; -} - -for( int R = 2; R <= 4; ++R ) -for( int C = 2; C <= 4; ++C ) -{ - sb << "__generic __extension matrix\n{\n"; - - // initialize from R*C scalars - sb << "__init("; - for( int ii = 0; ii < R; ++ii ) - for( int jj = 0; jj < C; ++jj ) - { - if ((ii+jj) != 0) sb << ", "; - sb << "T m" << ii << jj; - } - sb << ");\n"; - - // Initialize from R C-vectors - sb << "__init("; - for (int ii = 0; ii < R; ++ii) - { - if(ii != 0) sb << ", "; - sb << "vector row" << ii; - } - sb << ");\n"; - - - // initialize from another matrix of the same size - // - // TODO(tfoley): See comment about how this overlaps - // with implicit conversion, in the `vector` case above - sb << "__generic __init(matrix);\n"; - - // initialize from a matrix of larger size - for(int rr = R; rr <= 4; ++rr) - for( int cc = C; cc <= 4; ++cc ) - { - if(rr == R && cc == C) continue; - sb << "__init(matrix value);\n"; - } - - sb << "}\n"; -} - -// Declare built-in texture and sampler types - - - -sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerState) << ")\n"; -sb << "__intrinsic_type(" << kIROp_SamplerType << ", " << int(SamplerStateType::Flavor::SamplerState) << ")\n"; -sb << "struct SamplerState {};"; - -sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerComparisonState) << ")\n"; -sb << "__intrinsic_type(" << kIROp_SamplerType << ", " << int(SamplerStateType::Flavor::SamplerComparisonState) << ")\n"; -sb << "struct SamplerComparisonState {};"; - -// TODO(tfoley): Need to handle `RW*` variants of texture types as well... -static const struct { - char const* name; - TextureType::Shape baseShape; - int coordCount; -} kBaseTextureTypes[] = { - { "Texture1D", TextureType::Shape1D, 1 }, - { "Texture2D", TextureType::Shape2D, 2 }, - { "Texture3D", TextureType::Shape3D, 3 }, - { "TextureCube", TextureType::ShapeCube, 3 }, -}; -static const int kBaseTextureTypeCount = sizeof(kBaseTextureTypes) / sizeof(kBaseTextureTypes[0]); - - -static const struct { - char const* name; - SlangResourceAccess access; -} kBaseTextureAccessLevels[] = { - { "", SLANG_RESOURCE_ACCESS_READ }, - { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE }, - { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED }, -}; -static const int kBaseTextureAccessLevelCount = sizeof(kBaseTextureAccessLevels) / sizeof(kBaseTextureAccessLevels[0]); - -for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) -{ - char const* name = kBaseTextureTypes[tt].name; - TextureType::Shape baseShape = kBaseTextureTypes[tt].baseShape; - - for (int isArray = 0; isArray < 2; ++isArray) - { - // Arrays of 3D textures aren't allowed - if (isArray && baseShape == TextureType::Shape3D) continue; - - for (int isMultisample = 0; isMultisample < 2; ++isMultisample) - for (int accessLevel = 0; accessLevel < kBaseTextureAccessLevelCount; ++accessLevel) - { - auto access = kBaseTextureAccessLevels[accessLevel].access; - - // TODO: any constraints to enforce on what gets to be multisampled? - - unsigned flavor = baseShape; - if (isArray) flavor |= TextureType::ArrayFlag; - if (isMultisample) flavor |= TextureType::MultisampleFlag; -// if (isShadow) flavor |= TextureType::ShadowFlag; - - flavor |= (access << 8); - - // emit a generic signature - // TODO: allow for multisample count to come in as well... - sb << "__generic "; - - sb << "__magic_type(Texture," << int(flavor) << ")\n"; - sb << "__intrinsic_type(" << kIROp_TextureType << ", " << flavor << ")\n"; - sb << "struct "; - sb << kBaseTextureAccessLevels[accessLevel].name; - sb << name; - if (isMultisample) sb << "MS"; - if (isArray) sb << "Array"; -// if (isShadow) sb << "Shadow"; - sb << "\n{"; - - if( !isMultisample ) - { - sb << "float CalculateLevelOfDetail(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n"; - - sb << "float CalculateLevelOfDetailUnclamped(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n"; - } - - // `GetDimensions` - - for(int isFloat = 0; isFloat < 2; ++isFloat) - for(int includeMipInfo = 0; includeMipInfo < 2; ++includeMipInfo) - { - { - sb << "__glsl_version(450)\n"; - sb << "__target_intrinsic(glsl, \"("; - - int aa = 0; - String lodStr = "0"; - if (includeMipInfo) - { - int mipLevelArg = aa++; - lodStr = "int($"; - lodStr.append(mipLevelArg); - lodStr.append(")"); - } - - int cc = 0; - switch(baseShape) - { - case TextureType::Shape1D: - sb << "($" << aa++ << " = textureSize($P, " << lodStr << "))"; - cc = 1; - break; - - case TextureType::Shape2D: - case TextureType::ShapeCube: - sb << "($" << aa++ << " = textureSize($P, " << lodStr << ").x)"; - sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").y)"; - cc = 2; - break; - - case TextureType::Shape3D: - sb << "($" << aa++ << " = textureSize($P, " << lodStr << ").x)"; - sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").y)"; - sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").z)"; - cc = 3; - break; - - default: - SLANG_UNEXPECTED("unhandled resource shape"); - break; - } - - if(isArray) - { - sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ")." << kComponentNames[cc] << ")"; - } - - if(isMultisample) - { - sb << ", ($" << aa++ << " = textureSamples($P))"; - } - - if (includeMipInfo) - { - sb << ", ($" << aa++ << " = textureQueryLevels($P))"; - } - - - sb << ")\")\n"; - - - // TIM: Making `GetDimensions` *not* be marked as - // an intrinsic, just so we can see how defining - // things as `extern` functions would work. -// sb << "__intrinsic_op\n"; - - } - - char const* t = isFloat ? "out float " : "out uint "; - - sb << "void GetDimensions("; - if(includeMipInfo) - sb << "uint mipLevel, "; - - switch(baseShape) - { - case TextureType::Shape1D: - sb << t << "width"; - break; - - case TextureType::Shape2D: - case TextureType::ShapeCube: - sb << t << "width,"; - sb << t << "height"; - break; - - case TextureType::Shape3D: - sb << t << "width,"; - sb << t << "height,"; - sb << t << "depth"; - break; - - default: - assert(!"unexpected"); - break; - } - - if(isArray) - { - sb << ", " << t << "elements"; - } - - if(isMultisample) - { - sb << ", " << t << "sampleCount"; - } - - if(includeMipInfo) - sb << ", " << t << "numberOfLevels"; - - sb << ");\n"; - } - - // `GetSamplePosition()` - if( isMultisample ) - { - sb << "float2 GetSamplePosition(int s);\n"; - } - - // `Load()` - - if( kBaseTextureTypes[tt].coordCount + isArray < 4 ) - { - int loadCoordCount = kBaseTextureTypes[tt].coordCount + isArray + (isMultisample?0:1); - - // When translating to GLSL, we need to break apart the `location` argument. - // - // TODO: this should realy be handled by having this member actually get lowered! - static const char* kGLSLLoadCoordsSwizzle[] = { "", "", "x", "xy", "xyz", "xyzw" }; - static const char* kGLSLLoadLODSwizzle[] = { "", "", "y", "z", "w", "error" }; - - if (isMultisample) - { - sb << "__target_intrinsic(glsl, \"texelFetch($P, $0, $1)\")\n"; - } - else - { - sb << "__target_intrinsic(glsl, \"texelFetch($P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n"; - } - sb << "__intrinsic_op\n"; - sb << "T Load("; - sb << "int" << loadCoordCount << " location"; - if(isMultisample) - { - sb << ", int sampleIndex"; - } - sb << ");\n"; - - if (isMultisample) - { - sb << "__target_intrinsic(glsl, \"texelFetchOffset($P, $0, $1, $2)\")\n"; - } - else - { - sb << "__target_intrinsic(glsl, \"texelFetch($P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $1)\")\n"; - } - sb << "__intrinsic_op\n"; - sb << "T Load("; - sb << "int" << loadCoordCount << " location"; - if(isMultisample) - { - sb << ", int sampleIndex"; - } - sb << ", int" << loadCoordCount << " offset"; - sb << ");\n"; - - - sb << "T Load("; - sb << "int" << loadCoordCount << " location"; - if(isMultisample) - { - sb << ", int sampleIndex"; - } - sb << ", int" << kBaseTextureTypes[tt].coordCount << " offset"; - sb << ", out uint status"; - sb << ");\n"; - } - - if(baseShape != TextureType::ShapeCube) - { - // subscript operator - sb << "__intrinsic_op __subscript(uint" << kBaseTextureTypes[tt].coordCount + isArray << " location) -> T;\n"; - } - - if( !isMultisample ) - { - // `Sample()` - - sb << "__target_intrinsic(glsl, \"texture($p, $1)\")\n"; - - // TODO: only enable if IR is being used? - sb << "__intrinsic_op(sample)\n"; - - sb << "__intrinsic_op\n"; - sb << "T Sample(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location);\n"; - - if( baseShape != TextureType::ShapeCube ) - { - sb << "__target_intrinsic(glsl, \"textureOffset($p, $1, $2)\")\n"; - sb << "__intrinsic_op\n"; - sb << "T Sample(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; - } - - sb << "T Sample(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; - if( baseShape != TextureType::ShapeCube ) - { - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, "; - } - sb << "float clamp);\n"; - - sb << "T Sample(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; - if( baseShape != TextureType::ShapeCube ) - { - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, "; - } - sb << "float clamp, out uint status);\n"; - - - // `SampleBias()` - sb << "__target_intrinsic(glsl, \"texture($p, $1, $2)\")\n"; - sb << "__intrinsic_op\n"; - sb << "T SampleBias(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias);\n"; - - if( baseShape != TextureType::ShapeCube ) - { - sb << "__target_intrinsic(glsl, \"textureOffset($p, $1, $2, $3)\")\n"; - sb << "__intrinsic_op\n"; - sb << "T SampleBias(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; - } - - // `SampleCmp()` and `SampleCmpLevelZero` - sb << "T SampleCmp(SamplerComparisonState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; - sb << "float compareValue"; - sb << ");\n"; - - int baseCoordCount = kBaseTextureTypes[tt].coordCount; - int arrCoordCount = baseCoordCount + isArray; - if (arrCoordCount < 3) - { - int extCoordCount = arrCoordCount + 1; - - if (extCoordCount < 3) - extCoordCount = 3; - - sb << "__target_intrinsic(glsl, \"textureLod($p, "; - - sb << "vec" << extCoordCount << "($1,"; - for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii) - { - sb << " 0.0,"; - } - sb << "$2)"; - - sb << ", 0.0)\")\n"; - } - else if(arrCoordCount <= 3) - { - int extCoordCount = arrCoordCount + 1; - - if (extCoordCount < 3) - extCoordCount = 3; - - sb << "__target_intrinsic(glsl, \"textureGrad($p, "; - - sb << "vec" << extCoordCount << "($1,"; - for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii) - { - sb << " 0.0,"; - } - sb << "$2)"; - - // Construct gradients - sb << ", vec" << baseCoordCount << "(0.0)"; - sb << ", vec" << baseCoordCount << "(0.0)"; - sb << ")\")\n"; - } - sb << "__intrinsic_op\n"; - sb << "T SampleCmpLevelZero(SamplerComparisonState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; - sb << "float compareValue"; - sb << ");\n"; - - if( baseShape != TextureType::ShapeCube ) - { - // Note(tfoley): MSDN seems confused, and claims that the `offset` - // parameter for `SampleCmp` is available for everything but 3D - // textures, while `Sample` and `SampleBias` are consistent in - // saying they only exclude `offset` for cube maps (which makes - // sense). I'm going to assume the documentation for `SampleCmp` - // is just wrong. - - sb << "T SampleCmp(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; - sb << "float compareValue, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; - - sb << "T SampleCmpLevelZero(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; - sb << "float compareValue, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; - } - - - sb << "__target_intrinsic(glsl, \"textureGrad($p, $1, $2, $3)\")\n"; - sb << "__intrinsic_op(sampleGrad)\n"; - sb << "T SampleGrad(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; - sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, "; - sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY"; - sb << ");\n"; - - if( baseShape != TextureType::ShapeCube ) - { - sb << "__target_intrinsic(glsl, \"textureGradOffset($p, $1, $2, $3, $4)\")\n"; - sb << "__intrinsic_op(sampleGrad)\n"; - sb << "T SampleGrad(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; - sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, "; - sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; - } - - // `SampleLevel` - - sb << "__target_intrinsic(glsl, \"textureLod($p, $1, $2)\")\n"; - sb << "__intrinsic_op\n"; - sb << "T SampleLevel(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; - sb << "float level);\n"; - - if( baseShape != TextureType::ShapeCube ) - { - sb << "__target_intrinsic(glsl, \"textureLodOffset($p, $1, $2, $3)\")\n"; - sb << "__intrinsic_op\n"; - sb << "T SampleLevel(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; - sb << "float level, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; - } - } - - sb << "\n};\n"; - - // `Gather*()` operations are handled via an `extension` declaration, - // because this lets us capture the element type of the texture. - // - // TODO: longer-term there should be something like a `TextureElementType` - // interface, that both scalars and vectors implement, that then exposes - // a `Scalar` associated type, and `Gather` can return `vector`. - // - static const struct { - char const* genericPrefix; - char const* elementType; - } kGatherExtensionCases[] = { - { "__generic", "vector" }, - - // TODO: need a case here for scalars `T`, but also - // need to ensure that case doesn't accidentally match - // for `T = vector<...>`, which requires actual checking - // of constraints on generic parameters. - }; - for(auto cc : kGatherExtensionCases) - { - // TODO: this should really be an `if` around the entire `Gather` logic - if (isMultisample) break; - - EMIT_LINE_DIRECTIVE(); - sb << cc.genericPrefix << " __extension "; - sb << kBaseTextureAccessLevels[accessLevel].name; - sb << name; - if (isArray) sb << "Array"; - sb << "<" << cc.elementType << " >"; - sb << "\n{\n"; - - - // `Gather` - // (tricky because it returns a 4-vector of the element type - // of the texture components...) - // - // TODO: is it actually correct to restrict these so that, e.g., - // `GatherAlpha()` isn't allowed on `Texture2D` because - // it nominally doesn't have an alpha component? - static const struct { - int componentIndex; - char const* componentName; - } kGatherComponets[] = { - { 0, "" }, - { 0, "Red" }, - { 1, "Green" }, - { 2, "Blue" }, - { 3, "Alpha" }, - }; - - for(auto kk : kGatherComponets) - { - auto componentIndex = kk.componentIndex; - auto componentName = kk.componentName; - - EMIT_LINE_DIRECTIVE(); - - sb << "__target_intrinsic(glsl, \"textureGather($p, $1, " << componentIndex << ")\")\n"; - sb << "__intrinsic_op\n"; - sb << "vector Gather" << componentName << "(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n"; - - EMIT_LINE_DIRECTIVE(); - sb << "__target_intrinsic(glsl, \"textureGatherOffset($p, $1, $2, " << componentIndex << ")\")\n"; - sb << "__intrinsic_op\n"; - sb << "vector Gather" << componentName << "(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount << " location, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; - - EMIT_LINE_DIRECTIVE(); - sb << "vector Gather" << componentName << "(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount << " location, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, "; - sb << "out uint status);\n"; - - EMIT_LINE_DIRECTIVE(); - sb << "__target_intrinsic(glsl, \"textureGatherOffsets($p, $1, int" << kBaseTextureTypes[tt].coordCount << "[]($2, $3, $4, $5), " << componentIndex << ")\")\n"; - sb << "__intrinsic_op\n"; - sb << "vector Gather" << componentName << "(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount << " location, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset2, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset3, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset4);\n"; - - EMIT_LINE_DIRECTIVE(); - sb << "vector Gather" << componentName << "(SamplerState s, "; - sb << "float" << kBaseTextureTypes[tt].coordCount << " location, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset2, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset3, "; - sb << "int" << kBaseTextureTypes[tt].coordCount << " offset4, "; - sb << "out uint status);\n"; - } - - EMIT_LINE_DIRECTIVE(); - sb << "\n}\n"; - } - } - } -} - - -for (auto op : unaryOps) -{ - for (auto type : kBaseTypes) - { - if ((type.flags & op.flags) == 0) - continue; - - char const* fixity = (op.flags & POSTFIX) != 0 ? "__postfix " : "__prefix "; - char const* qual = (op.flags & ASSIGNMENT) != 0 ? "in out " : ""; - - // scalar version - sb << fixity; - sb << "__intrinsic_op(" << int(op.opCode) << ") " << type.name << " operator" << op.opName << "(" << qual << type.name << " value);\n"; - - // vector version - sb << "__generic "; - sb << fixity; - sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << type.name << ",N> operator" << op.opName << "(" << qual << "vector<" << type.name << ",N> value);\n"; - - // matrix version - sb << "__generic "; - sb << fixity; - sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << type.name << ",N,M> operator" << op.opName << "(" << qual << "matrix<" << type.name << ",N,M> value);\n"; - } -} - -for (auto op : binaryOps) -{ - for (auto type : kBaseTypes) - { - if ((type.flags & op.flags) == 0) - continue; - - char const* leftType = type.name; - char const* rightType = leftType; - char const* resultType = leftType; - - if (op.flags & COMPARISON) resultType = "bool"; - - char const* leftQual = ""; - if(op.flags & ASSIGNMENT) leftQual = "in out "; - - // TODO: handle `SHIFT` - - // scalar version - sb << "__intrinsic_op(" << int(op.opCode) << ") " << resultType << " operator" << op.opName << "(" << leftQual << leftType << " left, " << rightType << " right);\n"; - - // vector version - sb << "__generic "; - sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, vector<" << rightType << ",N> right);\n"; - - // matrix version - - // skip matrix-matrix multiply operations here, so that GLSL doesn't see them - switch (op.opCode) - { - case kIROp_Mul: - case kIRPseudoOp_MulAssign: - break; - - default: - sb << "__generic "; - sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n"; - break; - } - - // We are going to go ahead and explicitly define combined - // operations for the scalar-op-vector, etc. cases, rather - // than rely on promotion rules. - - // scalar-vector and scalar-matrix - if (!(op.flags & ASSIGNMENT)) - { - sb << "__generic "; - sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << leftType << " left, vector<" << rightType << ",N> right);\n"; - - sb << "__generic "; - sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << leftType << " left, matrix<" << rightType << ",N,M> right);\n"; - } - - // vector-scalar and matrix-scalar - sb << "__generic "; - sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, " << rightType << " right);\n"; - - sb << "__generic "; - sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, " << rightType << " right);\n"; - } -} - -sb << "\n"; -sb << ""; diff --git a/source/slang/core.meta.slang.h b/source/slang/core.meta.slang.h new file mode 100644 index 000000000..cf2052d3c --- /dev/null +++ b/source/slang/core.meta.slang.h @@ -0,0 +1,916 @@ +sb << "// Slang `core` library\n"; +sb << "\n"; +sb << "// A type that can be used as an operand for builtins\n"; +sb << "interface __BuiltinType {}\n"; +sb << "\n"; +sb << "// A type that can be used for arithmetic operations\n"; +sb << "interface __BuiltinArithmeticType : __BuiltinType {}\n"; +sb << "\n"; +sb << "// A type that logically has a sign (positive/negative/zero)\n"; +sb << "interface __BuiltinSignedArithmeticType : __BuiltinArithmeticType {}\n"; +sb << "\n"; +sb << "// A type that can represent integers\n"; +sb << "interface __BuiltinIntegerType : __BuiltinArithmeticType {}\n"; +sb << "\n"; +sb << "// A type that can represent non-integers\n"; +sb << "interface __BuiltinRealType : __BuiltinArithmeticType {}\n"; +sb << "\n"; +sb << "// A type that uses a floating-point representation\n"; +sb << "interface __BuiltinFloatingPointType : __BuiltinRealType, __BuiltinSignedArithmeticType {}\n"; +sb << "\n"; +sb << "__generic __intrinsic_op(Sequence) U operator,(T left, U right);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op(select) T operator?:(bool condition, T ifTrue, T ifFalse);\n"; +sb << "__generic __intrinsic_op(select) vector operator?:(vector condition, vector ifTrue, vector ifFalse);\n"; +sb << "\n"; +sb << ""; + +// We are going to use code generation to produce the +// declarations for all of our base types. + +static const int kBaseTypeCount = sizeof(kBaseTypes) / sizeof(kBaseTypes[0]); +for (int tt = 0; tt < kBaseTypeCount; ++tt) +{ + EMIT_LINE_DIRECTIVE(); + sb << "__builtin_type(" << int(kBaseTypes[tt].tag) << ") struct " << kBaseTypes[tt].name; + + // Declare interface conformances for this type + + sb << "\n : __BuiltinType\n"; + + switch (kBaseTypes[tt].tag) + { + case BaseType::Float: + sb << "\n , __BuiltinFloatingPointType\n"; + sb << "\n , __BuiltinRealType\n"; + // fall through to: + case BaseType::Int: + sb << "\n , __BuiltinSignedArithmeticType\n"; + // fall through to: + case BaseType::UInt: + case BaseType::UInt64: + sb << "\n , __BuiltinArithmeticType\n"; + // fall through to: + case BaseType::Bool: + sb << "\n , __BuiltinType\n"; + break; + + default: + break; + } + + sb << "\n{\n"; + + + // Declare initializers to convert from various other types + for (int ss = 0; ss < kBaseTypeCount; ++ss) + { + // Don't allow conversion from `void` + if (kBaseTypes[ss].tag == BaseType::Void) + continue; + + // We need to emit a modifier so that the semantic-checking + // layer will know it can use these operations for implicit + // conversion. + ConversionCost conversionCost = getBaseTypeConversionCost( + kBaseTypes[tt], + kBaseTypes[ss]); + + EMIT_LINE_DIRECTIVE(); + sb << "__implicit_conversion(" << conversionCost << ")\n"; + + EMIT_LINE_DIRECTIVE(); + sb << "__init(" << kBaseTypes[ss].name << " value);\n"; + } + + sb << "};\n"; +} + + + +// Declare vector and matrix types + +sb << "__generic __magic_type(Vector) struct vector\n{\n"; +sb << " typedef T Element;\n"; + +// Declare initializer taking a single scalar of the elemnt type +sb << " __implicit_conversion(" << kConversionCost_ScalarToVector << ")\n"; +sb << " __intrinsic_op(" << kIROp_constructVectorFromScalar << ")\n"; +sb << " __init(T value);\n"; + +sb << "};\n"; + +// TODO: Probably need to do similar +sb << "\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__magic_type(Matrix)\n"; +sb << "struct matrix {};\n"; +sb << "\n"; +sb << ""; + + + + +static const struct { + char const* name; + char const* glslPrefix; +} kTypes[] = +{ + {"float", ""}, + {"int", "i"}, + {"uint", "u"}, + {"bool", "b"}, +}; +static const int kTypeCount = sizeof(kTypes) / sizeof(kTypes[0]); + +for (int tt = 0; tt < kTypeCount; ++tt) +{ + // Declare HLSL vector types + for (int ii = 1; ii <= 4; ++ii) + { + sb << "typedef vector<" << kTypes[tt].name << "," << ii << "> " << kTypes[tt].name << ii << ";\n"; + } + + // Declare HLSL matrix types + for (int rr = 2; rr <= 4; ++rr) + for (int cc = 2; cc <= 4; ++cc) + { + sb << "typedef matrix<" << kTypes[tt].name << "," << rr << "," << cc << "> " << kTypes[tt].name << rr << "x" << cc << ";\n"; + } +} + +// Declare additional built-in generic types +// EMIT_LINE_DIRECTIVE(); + + +sb << "__generic\n"; +sb << "__intrinsic_type(" << kIROp_ConstantBufferType << ")\n"; +sb << "__magic_type(ConstantBuffer) struct ConstantBuffer {};\n"; + +sb << "__generic\n"; +sb << "__intrinsic_type(" << kIROp_TextureBufferType << ")\n"; +sb << "__magic_type(TextureBuffer) struct TextureBuffer {};\n"; + + +static const char* kComponentNames[]{ "x", "y", "z", "w" }; +static const char* kVectorNames[]{ "", "x", "xy", "xyz", "xyzw" }; + +// Need to add constructors to the types above +for (int N = 2; N <= 4; ++N) +{ + sb << "__generic __extension vector\n{\n"; + + // initialize from N scalars + sb << "__init("; + for (int ii = 0; ii < N; ++ii) + { + if (ii != 0) sb << ", "; + sb << "T " << kComponentNames[ii]; + } + sb << ");\n"; + + // Initialize from an M-vector and then scalars + for (int M = 2; M < N; ++M) + { + sb << "__init(vector " << kVectorNames[M]; + for (int ii = M; ii < N; ++ii) + { + sb << ", T " << kComponentNames[ii]; + } + sb << ");\n"; + } + + // initialize from another vector of the same size + // + // TODO(tfoley): this overlaps with implicit conversions. + // We should look for a way that we can define implicit + // conversions directly in the stdlib instead... + sb << "__generic __init(vector);\n"; + + // Initialize from two vectors, of size M and N-M + for(int M = 2; M <= (N-2); ++M) + { + int K = N - M; + SLANG_ASSERT(K >= 2); + + sb << "__init(vector " << kVectorNames[M]; + sb << ", vector "; + for (int ii = 0; ii < K; ++ii) + { + sb << kComponentNames[ii]; + } + sb << ");\n"; + } + + sb << "}\n"; +} + +// The above extension was generic in the *type* of the vector, +// but explicit in the *size*. We will now declare an extension +// for each builtin type that is generic in the size. +// +for (int tt = 0; tt < kBaseTypeCount; ++tt) +{ + if(kBaseTypes[tt].tag == BaseType::Void) continue; + + sb << "__generic __extension vector<" + << kBaseTypes[tt].name << ",N>\n{\n"; + + for (int ff = 0; ff < kBaseTypeCount; ++ff) + { + if(kBaseTypes[ff].tag == BaseType::Void) continue; + + // We need a constructor to make a vector from a scalar + // of another type. + + if( tt != ff ) + { + auto cost = getBaseTypeConversionCost( + kBaseTypes[tt], + kBaseTypes[ff]); + cost += kConversionCost_ScalarToVector; + + sb << " __implicit_conversion(" << cost << ")\n"; + sb << " __init(" << kBaseTypes[ff].name << " value);\n"; + } + } + + sb << "}\n"; +} + +for( int R = 2; R <= 4; ++R ) +for( int C = 2; C <= 4; ++C ) +{ + sb << "__generic __extension matrix\n{\n"; + + // initialize from R*C scalars + sb << "__init("; + for( int ii = 0; ii < R; ++ii ) + for( int jj = 0; jj < C; ++jj ) + { + if ((ii+jj) != 0) sb << ", "; + sb << "T m" << ii << jj; + } + sb << ");\n"; + + // Initialize from R C-vectors + sb << "__init("; + for (int ii = 0; ii < R; ++ii) + { + if(ii != 0) sb << ", "; + sb << "vector row" << ii; + } + sb << ");\n"; + + + // initialize from another matrix of the same size + // + // TODO(tfoley): See comment about how this overlaps + // with implicit conversion, in the `vector` case above + sb << "__generic __init(matrix);\n"; + + // initialize from a matrix of larger size + for(int rr = R; rr <= 4; ++rr) + for( int cc = C; cc <= 4; ++cc ) + { + if(rr == R && cc == C) continue; + sb << "__init(matrix value);\n"; + } + + sb << "}\n"; +} + +// Declare built-in texture and sampler types + + + +sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerState) << ")\n"; +sb << "__intrinsic_type(" << kIROp_SamplerType << ", " << int(SamplerStateType::Flavor::SamplerState) << ")\n"; +sb << "struct SamplerState {};"; + +sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerComparisonState) << ")\n"; +sb << "__intrinsic_type(" << kIROp_SamplerType << ", " << int(SamplerStateType::Flavor::SamplerComparisonState) << ")\n"; +sb << "struct SamplerComparisonState {};"; + +// TODO(tfoley): Need to handle `RW*` variants of texture types as well... +static const struct { + char const* name; + TextureType::Shape baseShape; + int coordCount; +} kBaseTextureTypes[] = { + { "Texture1D", TextureType::Shape1D, 1 }, + { "Texture2D", TextureType::Shape2D, 2 }, + { "Texture3D", TextureType::Shape3D, 3 }, + { "TextureCube", TextureType::ShapeCube, 3 }, +}; +static const int kBaseTextureTypeCount = sizeof(kBaseTextureTypes) / sizeof(kBaseTextureTypes[0]); + + +static const struct { + char const* name; + SlangResourceAccess access; +} kBaseTextureAccessLevels[] = { + { "", SLANG_RESOURCE_ACCESS_READ }, + { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE }, + { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED }, +}; +static const int kBaseTextureAccessLevelCount = sizeof(kBaseTextureAccessLevels) / sizeof(kBaseTextureAccessLevels[0]); + +for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) +{ + char const* name = kBaseTextureTypes[tt].name; + TextureType::Shape baseShape = kBaseTextureTypes[tt].baseShape; + + for (int isArray = 0; isArray < 2; ++isArray) + { + // Arrays of 3D textures aren't allowed + if (isArray && baseShape == TextureType::Shape3D) continue; + + for (int isMultisample = 0; isMultisample < 2; ++isMultisample) + for (int accessLevel = 0; accessLevel < kBaseTextureAccessLevelCount; ++accessLevel) + { + auto access = kBaseTextureAccessLevels[accessLevel].access; + + // TODO: any constraints to enforce on what gets to be multisampled? + + unsigned flavor = baseShape; + if (isArray) flavor |= TextureType::ArrayFlag; + if (isMultisample) flavor |= TextureType::MultisampleFlag; +// if (isShadow) flavor |= TextureType::ShadowFlag; + + flavor |= (access << 8); + + // emit a generic signature + // TODO: allow for multisample count to come in as well... + sb << "__generic "; + + sb << "__magic_type(Texture," << int(flavor) << ")\n"; + sb << "__intrinsic_type(" << kIROp_TextureType << ", " << flavor << ")\n"; + sb << "struct "; + sb << kBaseTextureAccessLevels[accessLevel].name; + sb << name; + if (isMultisample) sb << "MS"; + if (isArray) sb << "Array"; +// if (isShadow) sb << "Shadow"; + sb << "\n{"; + + if( !isMultisample ) + { + sb << "float CalculateLevelOfDetail(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n"; + + sb << "float CalculateLevelOfDetailUnclamped(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n"; + } + + // `GetDimensions` + + for(int isFloat = 0; isFloat < 2; ++isFloat) + for(int includeMipInfo = 0; includeMipInfo < 2; ++includeMipInfo) + { + { + sb << "__glsl_version(450)\n"; + sb << "__target_intrinsic(glsl, \"("; + + int aa = 0; + String lodStr = "0"; + if (includeMipInfo) + { + int mipLevelArg = aa++; + lodStr = "int($"; + lodStr.append(mipLevelArg); + lodStr.append(")"); + } + + int cc = 0; + switch(baseShape) + { + case TextureType::Shape1D: + sb << "($" << aa++ << " = textureSize($P, " << lodStr << "))"; + cc = 1; + break; + + case TextureType::Shape2D: + case TextureType::ShapeCube: + sb << "($" << aa++ << " = textureSize($P, " << lodStr << ").x)"; + sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").y)"; + cc = 2; + break; + + case TextureType::Shape3D: + sb << "($" << aa++ << " = textureSize($P, " << lodStr << ").x)"; + sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").y)"; + sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ").z)"; + cc = 3; + break; + + default: + SLANG_UNEXPECTED("unhandled resource shape"); + break; + } + + if(isArray) + { + sb << ", ($" << aa++ << " = textureSize($P, " << lodStr << ")." << kComponentNames[cc] << ")"; + } + + if(isMultisample) + { + sb << ", ($" << aa++ << " = textureSamples($P))"; + } + + if (includeMipInfo) + { + sb << ", ($" << aa++ << " = textureQueryLevels($P))"; + } + + + sb << ")\")\n"; + + + // TIM: Making `GetDimensions` *not* be marked as + // an intrinsic, just so we can see how defining + // things as `extern` functions would work. +// sb << "__intrinsic_op\n"; + + } + + char const* t = isFloat ? "out float " : "out uint "; + + sb << "void GetDimensions("; + if(includeMipInfo) + sb << "uint mipLevel, "; + + switch(baseShape) + { + case TextureType::Shape1D: + sb << t << "width"; + break; + + case TextureType::Shape2D: + case TextureType::ShapeCube: + sb << t << "width,"; + sb << t << "height"; + break; + + case TextureType::Shape3D: + sb << t << "width,"; + sb << t << "height,"; + sb << t << "depth"; + break; + + default: + assert(!"unexpected"); + break; + } + + if(isArray) + { + sb << ", " << t << "elements"; + } + + if(isMultisample) + { + sb << ", " << t << "sampleCount"; + } + + if(includeMipInfo) + sb << ", " << t << "numberOfLevels"; + + sb << ");\n"; + } + + // `GetSamplePosition()` + if( isMultisample ) + { + sb << "float2 GetSamplePosition(int s);\n"; + } + + // `Load()` + + if( kBaseTextureTypes[tt].coordCount + isArray < 4 ) + { + int loadCoordCount = kBaseTextureTypes[tt].coordCount + isArray + (isMultisample?0:1); + + // When translating to GLSL, we need to break apart the `location` argument. + // + // TODO: this should realy be handled by having this member actually get lowered! + static const char* kGLSLLoadCoordsSwizzle[] = { "", "", "x", "xy", "xyz", "xyzw" }; + static const char* kGLSLLoadLODSwizzle[] = { "", "", "y", "z", "w", "error" }; + + if (isMultisample) + { + sb << "__target_intrinsic(glsl, \"texelFetch($P, $0, $1)\")\n"; + } + else + { + sb << "__target_intrinsic(glsl, \"texelFetch($P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ")\")\n"; + } + sb << "__intrinsic_op\n"; + sb << "T Load("; + sb << "int" << loadCoordCount << " location"; + if(isMultisample) + { + sb << ", int sampleIndex"; + } + sb << ");\n"; + + if (isMultisample) + { + sb << "__target_intrinsic(glsl, \"texelFetchOffset($P, $0, $1, $2)\")\n"; + } + else + { + sb << "__target_intrinsic(glsl, \"texelFetch($P, ($0)." << kGLSLLoadCoordsSwizzle[loadCoordCount] << ", ($0)." << kGLSLLoadLODSwizzle[loadCoordCount] << ", $1)\")\n"; + } + sb << "__intrinsic_op\n"; + sb << "T Load("; + sb << "int" << loadCoordCount << " location"; + if(isMultisample) + { + sb << ", int sampleIndex"; + } + sb << ", int" << loadCoordCount << " offset"; + sb << ");\n"; + + + sb << "T Load("; + sb << "int" << loadCoordCount << " location"; + if(isMultisample) + { + sb << ", int sampleIndex"; + } + sb << ", int" << kBaseTextureTypes[tt].coordCount << " offset"; + sb << ", out uint status"; + sb << ");\n"; + } + + if(baseShape != TextureType::ShapeCube) + { + // subscript operator + sb << "__intrinsic_op __subscript(uint" << kBaseTextureTypes[tt].coordCount + isArray << " location) -> T;\n"; + } + + if( !isMultisample ) + { + // `Sample()` + + sb << "__target_intrinsic(glsl, \"texture($p, $1)\")\n"; + + // TODO: only enable if IR is being used? + sb << "__intrinsic_op(sample)\n"; + + sb << "__intrinsic_op\n"; + sb << "T Sample(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location);\n"; + + if( baseShape != TextureType::ShapeCube ) + { + sb << "__target_intrinsic(glsl, \"textureOffset($p, $1, $2)\")\n"; + sb << "__intrinsic_op\n"; + sb << "T Sample(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; + } + + sb << "T Sample(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; + if( baseShape != TextureType::ShapeCube ) + { + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, "; + } + sb << "float clamp);\n"; + + sb << "T Sample(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; + if( baseShape != TextureType::ShapeCube ) + { + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, "; + } + sb << "float clamp, out uint status);\n"; + + + // `SampleBias()` + sb << "__target_intrinsic(glsl, \"texture($p, $1, $2)\")\n"; + sb << "__intrinsic_op\n"; + sb << "T SampleBias(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias);\n"; + + if( baseShape != TextureType::ShapeCube ) + { + sb << "__target_intrinsic(glsl, \"textureOffset($p, $1, $2, $3)\")\n"; + sb << "__intrinsic_op\n"; + sb << "T SampleBias(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, float bias, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; + } + + // `SampleCmp()` and `SampleCmpLevelZero` + sb << "T SampleCmp(SamplerComparisonState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; + sb << "float compareValue"; + sb << ");\n"; + + int baseCoordCount = kBaseTextureTypes[tt].coordCount; + int arrCoordCount = baseCoordCount + isArray; + if (arrCoordCount < 3) + { + int extCoordCount = arrCoordCount + 1; + + if (extCoordCount < 3) + extCoordCount = 3; + + sb << "__target_intrinsic(glsl, \"textureLod($p, "; + + sb << "vec" << extCoordCount << "($1,"; + for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii) + { + sb << " 0.0,"; + } + sb << "$2)"; + + sb << ", 0.0)\")\n"; + } + else if(arrCoordCount <= 3) + { + int extCoordCount = arrCoordCount + 1; + + if (extCoordCount < 3) + extCoordCount = 3; + + sb << "__target_intrinsic(glsl, \"textureGrad($p, "; + + sb << "vec" << extCoordCount << "($1,"; + for (int ii = arrCoordCount; ii < extCoordCount - 1; ++ii) + { + sb << " 0.0,"; + } + sb << "$2)"; + + // Construct gradients + sb << ", vec" << baseCoordCount << "(0.0)"; + sb << ", vec" << baseCoordCount << "(0.0)"; + sb << ")\")\n"; + } + sb << "__intrinsic_op\n"; + sb << "T SampleCmpLevelZero(SamplerComparisonState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; + sb << "float compareValue"; + sb << ");\n"; + + if( baseShape != TextureType::ShapeCube ) + { + // Note(tfoley): MSDN seems confused, and claims that the `offset` + // parameter for `SampleCmp` is available for everything but 3D + // textures, while `Sample` and `SampleBias` are consistent in + // saying they only exclude `offset` for cube maps (which makes + // sense). I'm going to assume the documentation for `SampleCmp` + // is just wrong. + + sb << "T SampleCmp(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; + sb << "float compareValue, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; + + sb << "T SampleCmpLevelZero(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; + sb << "float compareValue, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; + } + + + sb << "__target_intrinsic(glsl, \"textureGrad($p, $1, $2, $3)\")\n"; + sb << "__intrinsic_op(sampleGrad)\n"; + sb << "T SampleGrad(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; + sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, "; + sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY"; + sb << ");\n"; + + if( baseShape != TextureType::ShapeCube ) + { + sb << "__target_intrinsic(glsl, \"textureGradOffset($p, $1, $2, $3, $4)\")\n"; + sb << "__intrinsic_op(sampleGrad)\n"; + sb << "T SampleGrad(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; + sb << "float" << kBaseTextureTypes[tt].coordCount << " gradX, "; + sb << "float" << kBaseTextureTypes[tt].coordCount << " gradY, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; + } + + // `SampleLevel` + + sb << "__target_intrinsic(glsl, \"textureLod($p, $1, $2)\")\n"; + sb << "__intrinsic_op\n"; + sb << "T SampleLevel(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; + sb << "float level);\n"; + + if( baseShape != TextureType::ShapeCube ) + { + sb << "__target_intrinsic(glsl, \"textureLodOffset($p, $1, $2, $3)\")\n"; + sb << "__intrinsic_op\n"; + sb << "T SampleLevel(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount + isArray << " location, "; + sb << "float level, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; + } + } + + sb << "\n};\n"; + + // `Gather*()` operations are handled via an `extension` declaration, + // because this lets us capture the element type of the texture. + // + // TODO: longer-term there should be something like a `TextureElementType` + // interface, that both scalars and vectors implement, that then exposes + // a `Scalar` associated type, and `Gather` can return `vector`. + // + static const struct { + char const* genericPrefix; + char const* elementType; + } kGatherExtensionCases[] = { + { "__generic", "vector" }, + + // TODO: need a case here for scalars `T`, but also + // need to ensure that case doesn't accidentally match + // for `T = vector<...>`, which requires actual checking + // of constraints on generic parameters. + }; + for(auto cc : kGatherExtensionCases) + { + // TODO: this should really be an `if` around the entire `Gather` logic + if (isMultisample) break; + + EMIT_LINE_DIRECTIVE(); + sb << cc.genericPrefix << " __extension "; + sb << kBaseTextureAccessLevels[accessLevel].name; + sb << name; + if (isArray) sb << "Array"; + sb << "<" << cc.elementType << " >"; + sb << "\n{\n"; + + + // `Gather` + // (tricky because it returns a 4-vector of the element type + // of the texture components...) + // + // TODO: is it actually correct to restrict these so that, e.g., + // `GatherAlpha()` isn't allowed on `Texture2D` because + // it nominally doesn't have an alpha component? + static const struct { + int componentIndex; + char const* componentName; + } kGatherComponets[] = { + { 0, "" }, + { 0, "Red" }, + { 1, "Green" }, + { 2, "Blue" }, + { 3, "Alpha" }, + }; + + for(auto kk : kGatherComponets) + { + auto componentIndex = kk.componentIndex; + auto componentName = kk.componentName; + + EMIT_LINE_DIRECTIVE(); + + sb << "__target_intrinsic(glsl, \"textureGather($p, $1, " << componentIndex << ")\")\n"; + sb << "__intrinsic_op\n"; + sb << "vector Gather" << componentName << "(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount << " location);\n"; + + EMIT_LINE_DIRECTIVE(); + sb << "__target_intrinsic(glsl, \"textureGatherOffset($p, $1, $2, " << componentIndex << ")\")\n"; + sb << "__intrinsic_op\n"; + sb << "vector Gather" << componentName << "(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount << " location, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset);\n"; + + EMIT_LINE_DIRECTIVE(); + sb << "vector Gather" << componentName << "(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount << " location, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset, "; + sb << "out uint status);\n"; + + EMIT_LINE_DIRECTIVE(); + sb << "__target_intrinsic(glsl, \"textureGatherOffsets($p, $1, int" << kBaseTextureTypes[tt].coordCount << "[]($2, $3, $4, $5), " << componentIndex << ")\")\n"; + sb << "__intrinsic_op\n"; + sb << "vector Gather" << componentName << "(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount << " location, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset2, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset3, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset4);\n"; + + EMIT_LINE_DIRECTIVE(); + sb << "vector Gather" << componentName << "(SamplerState s, "; + sb << "float" << kBaseTextureTypes[tt].coordCount << " location, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset1, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset2, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset3, "; + sb << "int" << kBaseTextureTypes[tt].coordCount << " offset4, "; + sb << "out uint status);\n"; + } + + EMIT_LINE_DIRECTIVE(); + sb << "\n}\n"; + } + } + } +} + + +for (auto op : unaryOps) +{ + for (auto type : kBaseTypes) + { + if ((type.flags & op.flags) == 0) + continue; + + char const* fixity = (op.flags & POSTFIX) != 0 ? "__postfix " : "__prefix "; + char const* qual = (op.flags & ASSIGNMENT) != 0 ? "in out " : ""; + + // scalar version + sb << fixity; + sb << "__intrinsic_op(" << int(op.opCode) << ") " << type.name << " operator" << op.opName << "(" << qual << type.name << " value);\n"; + + // vector version + sb << "__generic "; + sb << fixity; + sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << type.name << ",N> operator" << op.opName << "(" << qual << "vector<" << type.name << ",N> value);\n"; + + // matrix version + sb << "__generic "; + sb << fixity; + sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << type.name << ",N,M> operator" << op.opName << "(" << qual << "matrix<" << type.name << ",N,M> value);\n"; + } +} + +for (auto op : binaryOps) +{ + for (auto type : kBaseTypes) + { + if ((type.flags & op.flags) == 0) + continue; + + char const* leftType = type.name; + char const* rightType = leftType; + char const* resultType = leftType; + + if (op.flags & COMPARISON) resultType = "bool"; + + char const* leftQual = ""; + if(op.flags & ASSIGNMENT) leftQual = "in out "; + + // TODO: handle `SHIFT` + + // scalar version + sb << "__intrinsic_op(" << int(op.opCode) << ") " << resultType << " operator" << op.opName << "(" << leftQual << leftType << " left, " << rightType << " right);\n"; + + // vector version + sb << "__generic "; + sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, vector<" << rightType << ",N> right);\n"; + + // matrix version + + // skip matrix-matrix multiply operations here, so that GLSL doesn't see them + switch (op.opCode) + { + case kIROp_Mul: + case kIRPseudoOp_MulAssign: + break; + + default: + sb << "__generic "; + sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n"; + break; + } + + // We are going to go ahead and explicitly define combined + // operations for the scalar-op-vector, etc. cases, rather + // than rely on promotion rules. + + // scalar-vector and scalar-matrix + if (!(op.flags & ASSIGNMENT)) + { + sb << "__generic "; + sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << leftType << " left, vector<" << rightType << ",N> right);\n"; + + sb << "__generic "; + sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << leftType << " left, matrix<" << rightType << ",N,M> right);\n"; + } + + // vector-scalar and matrix-scalar + sb << "__generic "; + sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, " << rightType << " right);\n"; + + sb << "__generic "; + sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, " << rightType << " right);\n"; + } +} + +sb << "\n"; +sb << ""; diff --git a/source/slang/diagnostics.cpp b/source/slang/diagnostics.cpp index 65161db1d..da703e1b9 100644 --- a/source/slang/diagnostics.cpp +++ b/source/slang/diagnostics.cpp @@ -108,7 +108,7 @@ static void formatDiagnosticMessage(StringBuilder& sb, char const* format, int a if (!*spanEnd) return; - SLANG_API(*spanEnd == '$'); + SLANG_ASSERT(*spanEnd == '$'); spanEnd++; int d = *spanEnd++; switch (d) diff --git a/source/slang/emit.cpp b/source/slang/emit.cpp index 26b3b925b..d4c1be706 100644 --- a/source/slang/emit.cpp +++ b/source/slang/emit.cpp @@ -488,7 +488,7 @@ struct EmitVisitor void Emit(IntegerLiteralValue value) { char buffer[32]; - sprintf(buffer, "%lld", value); + sprintf(buffer, "%lld", (long long int)value); Emit(buffer); } @@ -823,7 +823,7 @@ struct EmitVisitor { if(auto basicElementType = type->As()) { - switch (basicElementType->BaseType) + switch (basicElementType->baseType) { case BaseType::Float: // no prefix @@ -1043,7 +1043,7 @@ struct EmitVisitor void visitBasicExpressionType(BasicExpressionType* basicType, TypeEmitArg const& arg) { auto declarator = arg.declarator; - switch (basicType->BaseType) + switch (basicType->baseType) { case BaseType::Void: Emit("void"); break; case BaseType::Int: Emit("int"); break; @@ -1208,7 +1208,7 @@ struct EmitVisitor } - emitTypeImpl(arrayType->BaseType, &arrayDeclarator); + emitTypeImpl(arrayType->baseType, &arrayDeclarator); } void EmitType( diff --git a/source/slang/glsl.meta.slang.cpp b/source/slang/glsl.meta.slang.cpp deleted file mode 100644 index e43a51ea9..000000000 --- a/source/slang/glsl.meta.slang.cpp +++ /dev/null @@ -1,206 +0,0 @@ -sb << "// Slang GLSL compatibility library\n"; -sb << "\n"; -sb << ""; - - -static const struct { - char const* name; - char const* glslPrefix; -} kTypes[] = -{ - {"float", ""}, - {"int", "i"}, - {"uint", "u"}, - {"bool", "b"}, -}; -static const int kTypeCount = sizeof(kTypes) / sizeof(kTypes[0]); - -for( int tt = 0; tt < kTypeCount; ++tt ) -{ - // Declare GLSL aliases for HLSL types - for (int vv = 2; vv <= 4; ++vv) - { - sb << "typedef vector<" << kTypes[tt].name << "," << vv << "> " << kTypes[tt].glslPrefix << "vec" << vv << ";\n"; - sb << "typedef matrix<" << kTypes[tt].name << "," << vv << "," << vv << "> " << kTypes[tt].glslPrefix << "mat" << vv << ";\n"; - } - for (int rr = 2; rr <= 4; ++rr) - for (int cc = 2; cc <= 4; ++cc) - { - sb << "typedef matrix<" << kTypes[tt].name << "," << rr << "," << cc << "> " << kTypes[tt].glslPrefix << "mat" << rr << "x" << cc << ";\n"; - } -} - -// Multiplication operations for vectors + matrices - -// scalar-vector and vector-scalar -sb << "__generic __intrinsic_op(mul) vector operator*(vector x, T y);\n"; -sb << "__generic __intrinsic_op(mul) vector operator*(T x, vector y);\n"; - -// scalar-matrix and matrix-scalar -sb << "__generic __intrinsic_op(mul) matrix operator*(matrix x, T y);\n"; -sb << "__generic __intrinsic_op(mul) matrix operator*(T x, matrix y);\n"; - -// vector-vector (dot product) -sb << "__generic __intrinsic_op(dot) T operator*(vector x, vector y);\n"; - -// vector-matrix -sb << "__generic __intrinsic_op(mulVectorMatrix) vector operator*(vector x, matrix y);\n"; - -// matrix-vector -sb << "__generic __intrinsic_op(mulMatrixVector) vector operator*(matrix x, vector y);\n"; - -// matrix-matrix -sb << "__generic __intrinsic_op(mulMatrixMatrix) matrix operator*(matrix x, matrix y);\n"; - - - -// - -// TODO(tfoley): Need to handle `RW*` variants of texture types as well... -static const struct { - char const* name; - TextureType::Shape baseShape; - int coordCount; -} kBaseTextureTypes[] = { - { "1D", TextureType::Shape1D, 1 }, - { "2D", TextureType::Shape2D, 2 }, - { "3D", TextureType::Shape3D, 3 }, - { "Cube", TextureType::ShapeCube, 3 }, - { "Buffer", TextureType::ShapeBuffer, 1 }, -}; -static const int kBaseTextureTypeCount = sizeof(kBaseTextureTypes) / sizeof(kBaseTextureTypes[0]); - - -static const struct { - char const* name; - SlangResourceAccess access; -} kBaseTextureAccessLevels[] = { - { "", SLANG_RESOURCE_ACCESS_READ }, - { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE }, - { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED }, -}; -static const int kBaseTextureAccessLevelCount = sizeof(kBaseTextureAccessLevels) / sizeof(kBaseTextureAccessLevels[0]); - -for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) -{ - char const* shapeName = kBaseTextureTypes[tt].name; - TextureType::Shape baseShape = kBaseTextureTypes[tt].baseShape; - - for (int isArray = 0; isArray < 2; ++isArray) - { - // Arrays of 3D textures aren't allowed - if (isArray && baseShape == TextureType::Shape3D) continue; - - for (int isMultisample = 0; isMultisample < 2; ++isMultisample) - { - auto readAccess = SLANG_RESOURCE_ACCESS_READ; - auto readWriteAccess = SLANG_RESOURCE_ACCESS_READ_WRITE; - - // TODO: any constraints to enforce on what gets to be multisampled? - - - unsigned flavor = baseShape; - if (isArray) flavor |= TextureType::ArrayFlag; - if (isMultisample) flavor |= TextureType::MultisampleFlag; -// if (isShadow) flavor |= TextureType::ShadowFlag; - - - - unsigned readFlavor = flavor | (readAccess << 8); - unsigned readWriteFlavor = flavor | (readWriteAccess << 8); - - StringBuilder nameBuilder; - nameBuilder << shapeName; - if (isMultisample) nameBuilder << "MS"; - if (isArray) nameBuilder << "Array"; - auto name = nameBuilder.ProduceString(); - - sb << "__generic "; - sb << "__magic_type(TextureSampler," << int(readFlavor) << ") struct "; - sb << "__sampler" << name; - sb << " {};\n"; - - sb << "__generic "; - sb << "__magic_type(Texture," << int(readFlavor) << ") struct "; - sb << "__texture" << name; - sb << " {};\n"; - - sb << "__generic "; - sb << "__magic_type(GLSLImageType," << int(readWriteFlavor) << ") struct "; - sb << "__image" << name; - sb << " {};\n"; - - // TODO(tfoley): flesh this out for all the available prefixes - static const struct - { - char const* prefix; - char const* elementType; - } kTextureElementTypes[] = { - { "", "vec4" }, - { "i", "ivec4" }, - { "u", "uvec4" }, - { nullptr, nullptr }, - }; - for( auto ee = kTextureElementTypes; ee->prefix; ++ee ) - { - sb << "typedef __sampler" << name << "<" << ee->elementType << "> " << ee->prefix << "sampler" << name << ";\n"; - sb << "typedef __texture" << name << "<" << ee->elementType << "> " << ee->prefix << "texture" << name << ";\n"; - sb << "typedef __image" << name << "<" << ee->elementType << "> " << ee->prefix << "image" << name << ";\n"; - } - } - } -} - -sb << "__generic __magic_type(GLSLInputParameterBlockType) struct __GLSLInputParameterBlock {};\n"; -sb << "__generic __magic_type(GLSLOutputParameterBlockType) struct __GLSLOutputParameterBlock {};\n"; -sb << "__generic __magic_type(GLSLShaderStorageBufferType) struct __GLSLShaderStorageBuffer {};\n"; - -sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerState) << ") struct sampler {};"; - -sb << "__magic_type(GLSLInputAttachmentType) struct subpassInput {};"; - -// Define additional keywords - -sb << "syntax buffer : GLSLBufferModifier;\n"; - -// [GLSL 4.3] Storage Qualifiers - -// TODO: need to support `shared` here with its GLSL meaning - -sb << "syntax patch : GLSLPatchModifier;\n"; -// `centroid` and `sample` handled centrally - -// [GLSL 4.5] Interpolation Qualifiers -sb << "syntax smooth : SimpleModifier;\n"; -sb << "syntax flat : SimpleModifier;\n"; -sb << "syntax noperspectie : SimpleModifier;\n"; - - -// [GLSL 4.3.2] Constant Qualifier - -// We need to handle GLSL `const` separately from HLSL `const`, -// since they mean such different things. - -// [GLSL 4.7.2] Precision Qualifiers -sb << "syntax highp : SimpleModifier;\n"; -sb << "syntax mediump : SimpleModifier;\n"; -sb << "syntax lowp : SimpleModifier;\n"; - -// [GLSL 4.8.1] The Invariant Qualifier - -sb << "syntax invariant : SimpleModifier;\n"; - -// [GLSL 4.10] Memory Qualifiers - -sb << "syntax coherent : SimpleModifier;\n"; -sb << "syntax volatile : SimpleModifier;\n"; -sb << "syntax restrict : SimpleModifier;\n"; -sb << "syntax readonly : GLSLReadOnlyModifier;\n"; -sb << "syntax writeonly : GLSLWriteOnlyModifier;\n"; - -// We will treat `subroutine` as a qualifier for now -sb << "syntax subroutine : SimpleModifier;\n"; - - - -sb << ""; diff --git a/source/slang/glsl.meta.slang.h b/source/slang/glsl.meta.slang.h new file mode 100644 index 000000000..e43a51ea9 --- /dev/null +++ b/source/slang/glsl.meta.slang.h @@ -0,0 +1,206 @@ +sb << "// Slang GLSL compatibility library\n"; +sb << "\n"; +sb << ""; + + +static const struct { + char const* name; + char const* glslPrefix; +} kTypes[] = +{ + {"float", ""}, + {"int", "i"}, + {"uint", "u"}, + {"bool", "b"}, +}; +static const int kTypeCount = sizeof(kTypes) / sizeof(kTypes[0]); + +for( int tt = 0; tt < kTypeCount; ++tt ) +{ + // Declare GLSL aliases for HLSL types + for (int vv = 2; vv <= 4; ++vv) + { + sb << "typedef vector<" << kTypes[tt].name << "," << vv << "> " << kTypes[tt].glslPrefix << "vec" << vv << ";\n"; + sb << "typedef matrix<" << kTypes[tt].name << "," << vv << "," << vv << "> " << kTypes[tt].glslPrefix << "mat" << vv << ";\n"; + } + for (int rr = 2; rr <= 4; ++rr) + for (int cc = 2; cc <= 4; ++cc) + { + sb << "typedef matrix<" << kTypes[tt].name << "," << rr << "," << cc << "> " << kTypes[tt].glslPrefix << "mat" << rr << "x" << cc << ";\n"; + } +} + +// Multiplication operations for vectors + matrices + +// scalar-vector and vector-scalar +sb << "__generic __intrinsic_op(mul) vector operator*(vector x, T y);\n"; +sb << "__generic __intrinsic_op(mul) vector operator*(T x, vector y);\n"; + +// scalar-matrix and matrix-scalar +sb << "__generic __intrinsic_op(mul) matrix operator*(matrix x, T y);\n"; +sb << "__generic __intrinsic_op(mul) matrix operator*(T x, matrix y);\n"; + +// vector-vector (dot product) +sb << "__generic __intrinsic_op(dot) T operator*(vector x, vector y);\n"; + +// vector-matrix +sb << "__generic __intrinsic_op(mulVectorMatrix) vector operator*(vector x, matrix y);\n"; + +// matrix-vector +sb << "__generic __intrinsic_op(mulMatrixVector) vector operator*(matrix x, vector y);\n"; + +// matrix-matrix +sb << "__generic __intrinsic_op(mulMatrixMatrix) matrix operator*(matrix x, matrix y);\n"; + + + +// + +// TODO(tfoley): Need to handle `RW*` variants of texture types as well... +static const struct { + char const* name; + TextureType::Shape baseShape; + int coordCount; +} kBaseTextureTypes[] = { + { "1D", TextureType::Shape1D, 1 }, + { "2D", TextureType::Shape2D, 2 }, + { "3D", TextureType::Shape3D, 3 }, + { "Cube", TextureType::ShapeCube, 3 }, + { "Buffer", TextureType::ShapeBuffer, 1 }, +}; +static const int kBaseTextureTypeCount = sizeof(kBaseTextureTypes) / sizeof(kBaseTextureTypes[0]); + + +static const struct { + char const* name; + SlangResourceAccess access; +} kBaseTextureAccessLevels[] = { + { "", SLANG_RESOURCE_ACCESS_READ }, + { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE }, + { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED }, +}; +static const int kBaseTextureAccessLevelCount = sizeof(kBaseTextureAccessLevels) / sizeof(kBaseTextureAccessLevels[0]); + +for (int tt = 0; tt < kBaseTextureTypeCount; ++tt) +{ + char const* shapeName = kBaseTextureTypes[tt].name; + TextureType::Shape baseShape = kBaseTextureTypes[tt].baseShape; + + for (int isArray = 0; isArray < 2; ++isArray) + { + // Arrays of 3D textures aren't allowed + if (isArray && baseShape == TextureType::Shape3D) continue; + + for (int isMultisample = 0; isMultisample < 2; ++isMultisample) + { + auto readAccess = SLANG_RESOURCE_ACCESS_READ; + auto readWriteAccess = SLANG_RESOURCE_ACCESS_READ_WRITE; + + // TODO: any constraints to enforce on what gets to be multisampled? + + + unsigned flavor = baseShape; + if (isArray) flavor |= TextureType::ArrayFlag; + if (isMultisample) flavor |= TextureType::MultisampleFlag; +// if (isShadow) flavor |= TextureType::ShadowFlag; + + + + unsigned readFlavor = flavor | (readAccess << 8); + unsigned readWriteFlavor = flavor | (readWriteAccess << 8); + + StringBuilder nameBuilder; + nameBuilder << shapeName; + if (isMultisample) nameBuilder << "MS"; + if (isArray) nameBuilder << "Array"; + auto name = nameBuilder.ProduceString(); + + sb << "__generic "; + sb << "__magic_type(TextureSampler," << int(readFlavor) << ") struct "; + sb << "__sampler" << name; + sb << " {};\n"; + + sb << "__generic "; + sb << "__magic_type(Texture," << int(readFlavor) << ") struct "; + sb << "__texture" << name; + sb << " {};\n"; + + sb << "__generic "; + sb << "__magic_type(GLSLImageType," << int(readWriteFlavor) << ") struct "; + sb << "__image" << name; + sb << " {};\n"; + + // TODO(tfoley): flesh this out for all the available prefixes + static const struct + { + char const* prefix; + char const* elementType; + } kTextureElementTypes[] = { + { "", "vec4" }, + { "i", "ivec4" }, + { "u", "uvec4" }, + { nullptr, nullptr }, + }; + for( auto ee = kTextureElementTypes; ee->prefix; ++ee ) + { + sb << "typedef __sampler" << name << "<" << ee->elementType << "> " << ee->prefix << "sampler" << name << ";\n"; + sb << "typedef __texture" << name << "<" << ee->elementType << "> " << ee->prefix << "texture" << name << ";\n"; + sb << "typedef __image" << name << "<" << ee->elementType << "> " << ee->prefix << "image" << name << ";\n"; + } + } + } +} + +sb << "__generic __magic_type(GLSLInputParameterBlockType) struct __GLSLInputParameterBlock {};\n"; +sb << "__generic __magic_type(GLSLOutputParameterBlockType) struct __GLSLOutputParameterBlock {};\n"; +sb << "__generic __magic_type(GLSLShaderStorageBufferType) struct __GLSLShaderStorageBuffer {};\n"; + +sb << "__magic_type(SamplerState," << int(SamplerStateType::Flavor::SamplerState) << ") struct sampler {};"; + +sb << "__magic_type(GLSLInputAttachmentType) struct subpassInput {};"; + +// Define additional keywords + +sb << "syntax buffer : GLSLBufferModifier;\n"; + +// [GLSL 4.3] Storage Qualifiers + +// TODO: need to support `shared` here with its GLSL meaning + +sb << "syntax patch : GLSLPatchModifier;\n"; +// `centroid` and `sample` handled centrally + +// [GLSL 4.5] Interpolation Qualifiers +sb << "syntax smooth : SimpleModifier;\n"; +sb << "syntax flat : SimpleModifier;\n"; +sb << "syntax noperspectie : SimpleModifier;\n"; + + +// [GLSL 4.3.2] Constant Qualifier + +// We need to handle GLSL `const` separately from HLSL `const`, +// since they mean such different things. + +// [GLSL 4.7.2] Precision Qualifiers +sb << "syntax highp : SimpleModifier;\n"; +sb << "syntax mediump : SimpleModifier;\n"; +sb << "syntax lowp : SimpleModifier;\n"; + +// [GLSL 4.8.1] The Invariant Qualifier + +sb << "syntax invariant : SimpleModifier;\n"; + +// [GLSL 4.10] Memory Qualifiers + +sb << "syntax coherent : SimpleModifier;\n"; +sb << "syntax volatile : SimpleModifier;\n"; +sb << "syntax restrict : SimpleModifier;\n"; +sb << "syntax readonly : GLSLReadOnlyModifier;\n"; +sb << "syntax writeonly : GLSLWriteOnlyModifier;\n"; + +// We will treat `subroutine` as a qualifier for now +sb << "syntax subroutine : SimpleModifier;\n"; + + + +sb << ""; diff --git a/source/slang/hlsl.meta.slang.cpp b/source/slang/hlsl.meta.slang.cpp deleted file mode 100644 index 49254ac60..000000000 --- a/source/slang/hlsl.meta.slang.cpp +++ /dev/null @@ -1,1089 +0,0 @@ -sb << "// Slang HLSL compatibility library\n"; -sb << "\n"; -sb << "typedef uint UINT;\n"; -sb << "\n"; -sb << "__generic __magic_type(HLSLAppendStructuredBufferType) struct AppendStructuredBuffer\n"; -sb << "{\n"; -sb << " __intrinsic_op void Append(T value);\n"; -sb << "\n"; -sb << " __intrinsic_op void GetDimensions(\n"; -sb << " out uint numStructs,\n"; -sb << " out uint stride);\n"; -sb << "};\n"; -sb << "\n"; -sb << "__magic_type(HLSLByteAddressBufferType) struct ByteAddressBuffer\n"; -sb << "{\n"; -sb << " __intrinsic_op void GetDimensions(\n"; -sb << " out uint dim);\n"; -sb << "\n"; -sb << " __intrinsic_op uint Load(int location);\n"; -sb << " __intrinsic_op uint Load(int location, out uint status);\n"; -sb << "\n"; -sb << " __intrinsic_op uint2 Load2(int location);\n"; -sb << " __intrinsic_op uint2 Load2(int location, out uint status);\n"; -sb << "\n"; -sb << " __intrinsic_op uint3 Load3(int location);\n"; -sb << " __intrinsic_op uint3 Load3(int location, out uint status);\n"; -sb << "\n"; -sb << " __intrinsic_op uint4 Load4(int location);\n"; -sb << " __intrinsic_op uint4 Load4(int location, out uint status);\n"; -sb << "};\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__magic_type(HLSLStructuredBufferType)\n"; -sb << "__intrinsic_type("; - - // TODO: we really need a simple way to write an "expression splice" - sb << kIROp_structuredBufferType; -sb << ")\n"; -sb << "struct StructuredBuffer\n"; -sb << "{\n"; -sb << " __intrinsic_op void GetDimensions(\n"; -sb << " out uint numStructs,\n"; -sb << " out uint stride);\n"; -sb << "\n"; -sb << " __intrinsic_op T Load(int location);\n"; -sb << " __intrinsic_op T Load(int location, out uint status);\n"; -sb << "\n"; -sb << " __intrinsic_op(bufferLoad)\n"; -sb << " __subscript(uint index) -> T;\n"; -sb << "};\n"; -sb << "\n"; -sb << "__generic __magic_type(HLSLConsumeStructuredBufferType) struct ConsumeStructuredBuffer\n"; -sb << "{\n"; -sb << " __intrinsic_op T Consume();\n"; -sb << "\n"; -sb << " __intrinsic_op void GetDimensions(\n"; -sb << " out uint numStructs,\n"; -sb << " out uint stride);\n"; -sb << "};\n"; -sb << "\n"; -sb << "__generic __magic_type(HLSLInputPatchType) struct InputPatch\n"; -sb << "{\n"; -sb << " __intrinsic_op __subscript(uint index) -> T;\n"; -sb << "};\n"; -sb << "\n"; -sb << "__generic __magic_type(HLSLOutputPatchType) struct OutputPatch\n"; -sb << "{\n"; -sb << " __intrinsic_op __subscript(uint index) -> T { set; }\n"; -sb << "};\n"; -sb << "\n"; -sb << "__magic_type(HLSLRWByteAddressBufferType) struct RWByteAddressBuffer\n"; -sb << "{\n"; -sb << " // Note(tfoley): supports alll operations from `ByteAddressBuffer`\n"; -sb << " // TODO(tfoley): can this be made a sub-type?\n"; -sb << "\n"; -sb << " __intrinsic_op void GetDimensions(\n"; -sb << " out uint dim);\n"; -sb << "\n"; -sb << " __intrinsic_op uint Load(int location);\n"; -sb << " __intrinsic_op uint Load(int location, out uint status);\n"; -sb << "\n"; -sb << " __intrinsic_op uint2 Load2(int location);\n"; -sb << " __intrinsic_op uint2 Load2(int location, out uint status);\n"; -sb << "\n"; -sb << " __intrinsic_op uint3 Load3(int location);\n"; -sb << " __intrinsic_op uint3 Load3(int location, out uint status);\n"; -sb << "\n"; -sb << " __intrinsic_op uint4 Load4(int location);\n"; -sb << " __intrinsic_op uint4 Load4(int location, out uint status);\n"; -sb << "\n"; -sb << " // Added operations:\n"; -sb << "\n"; -sb << " __intrinsic_op void InterlockedAdd(\n"; -sb << " UINT dest,\n"; -sb << " UINT value,\n"; -sb << " out UINT original_value);\n"; -sb << " __intrinsic_op void InterlockedAdd(\n"; -sb << " UINT dest,\n"; -sb << " UINT value);\n"; -sb << "\n"; -sb << " __intrinsic_op void InterlockedAnd(\n"; -sb << " UINT dest,\n"; -sb << " UINT value,\n"; -sb << " out UINT original_value);\n"; -sb << " __intrinsic_op void InterlockedAnd(\n"; -sb << " UINT dest,\n"; -sb << " UINT value);\n"; -sb << "\n"; -sb << " __intrinsic_op void InterlockedCompareExchange(\n"; -sb << " UINT dest,\n"; -sb << " UINT compare_value,\n"; -sb << " UINT value,\n"; -sb << " out UINT original_value);\n"; -sb << " __intrinsic_op void InterlockedCompareExchange(\n"; -sb << " UINT dest,\n"; -sb << " UINT compare_value,\n"; -sb << " UINT value);\n"; -sb << "\n"; -sb << " __intrinsic_op void InterlockedCompareStore(\n"; -sb << " UINT dest,\n"; -sb << " UINT compare_value,\n"; -sb << " UINT value);\n"; -sb << " __intrinsic_op void InterlockedCompareStore(\n"; -sb << " UINT dest,\n"; -sb << " UINT compare_value);\n"; -sb << "\n"; -sb << " __intrinsic_op void InterlockedExchange(\n"; -sb << " UINT dest,\n"; -sb << " UINT value,\n"; -sb << " out UINT original_value);\n"; -sb << " __intrinsic_op void InterlockedExchange(\n"; -sb << " UINT dest,\n"; -sb << " UINT value);\n"; -sb << "\n"; -sb << " __intrinsic_op void InterlockedMax(\n"; -sb << " UINT dest,\n"; -sb << " UINT value,\n"; -sb << " out UINT original_value);\n"; -sb << " __intrinsic_op void InterlockedMax(\n"; -sb << " UINT dest,\n"; -sb << " UINT value);\n"; -sb << "\n"; -sb << " __intrinsic_op void InterlockedMin(\n"; -sb << " UINT dest,\n"; -sb << " UINT value,\n"; -sb << " out UINT original_value);\n"; -sb << " __intrinsic_op void InterlockedMin(\n"; -sb << " UINT dest,\n"; -sb << " UINT value);\n"; -sb << "\n"; -sb << " __intrinsic_op void InterlockedOr(\n"; -sb << " UINT dest,\n"; -sb << " UINT value,\n"; -sb << " out UINT original_value);\n"; -sb << " __intrinsic_op void InterlockedOr(\n"; -sb << " UINT dest,\n"; -sb << " UINT value);\n"; -sb << "\n"; -sb << " __intrinsic_op void InterlockedXor(\n"; -sb << " UINT dest,\n"; -sb << " UINT value,\n"; -sb << " out UINT original_value);\n"; -sb << " __intrinsic_op void InterlockedXor(\n"; -sb << " UINT dest,\n"; -sb << " UINT value);\n"; -sb << "\n"; -sb << " __intrinsic_op void Store(\n"; -sb << " uint address,\n"; -sb << " uint value);\n"; -sb << "\n"; -sb << " __intrinsic_op void Store2(\n"; -sb << " uint address,\n"; -sb << " uint2 value);\n"; -sb << "\n"; -sb << " __intrinsic_op void Store3(\n"; -sb << " uint address,\n"; -sb << " uint3 value);\n"; -sb << "\n"; -sb << " __intrinsic_op void Store4(\n"; -sb << " uint address,\n"; -sb << " uint4 value);\n"; -sb << "};\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__magic_type(HLSLRWStructuredBufferType)\n"; -sb << "__intrinsic_type("; - - // TODO: we really need a simple way to write an "expression splice" - sb << kIROp_readWriteStructuredBufferType; -sb << ")\n"; -sb << "struct RWStructuredBuffer\n"; -sb << "{\n"; -sb << " __intrinsic_op uint DecrementCounter();\n"; -sb << "\n"; -sb << " __intrinsic_op void GetDimensions(\n"; -sb << " out uint numStructs,\n"; -sb << " out uint stride);\n"; -sb << "\n"; -sb << " __intrinsic_op void IncrementCounter();\n"; -sb << "\n"; -sb << " __intrinsic_op T Load(int location);\n"; -sb << " __intrinsic_op T Load(int location, out uint status);\n"; -sb << "\n"; -sb << "\t__intrinsic_op\n"; -sb << "\t__subscript(uint index) -> T\n"; -sb << "\t{\n"; -sb << "\t\t__intrinsic_op(bufferLoad)\n"; -sb << "\t\tget;\n"; -sb << "\n"; -sb << "\t\t__intrinsic_op(bufferStore)\n"; -sb << "\t\tset;\n"; -sb << "\t}\n"; -sb << "};\n"; -sb << "\n"; -sb << "__generic __magic_type(HLSLPointStreamType) struct PointStream\n"; -sb << "{\n"; -sb << " void Append(T value);\n"; -sb << " void RestartStrip();\n"; -sb << "};\n"; -sb << "\n"; -sb << "__generic __magic_type(HLSLLineStreamType) struct LineStream\n"; -sb << "{\n"; -sb << " void Append(T value);\n"; -sb << " void RestartStrip();\n"; -sb << "};\n"; -sb << "\n"; -sb << "__generic __magic_type(HLSLTriangleStreamType) struct TriangleStream\n"; -sb << "{\n"; -sb << " void Append(T value);\n"; -sb << " void RestartStrip();\n"; -sb << "};\n"; -sb << "\n"; -sb << "// Note(tfoley): Trying to systematically add all the HLSL builtins\n"; -sb << "\n"; -sb << "// Try to terminate the current draw or dispatch call (HLSL SM 4.0)\n"; -sb << "__intrinsic_op void abort();\n"; -sb << "\n"; -sb << "// Absolute value (HLSL SM 1.0)\n"; -sb << "__generic __intrinsic_op T abs(T x);\n"; -sb << "__generic __intrinsic_op vector abs(vector x);\n"; -sb << "__generic __intrinsic_op matrix abs(matrix x);\n"; -sb << "\n"; -sb << "// Inverse cosine (HLSL SM 1.0)\n"; -sb << "__generic __intrinsic_op T acos(T x);\n"; -sb << "__generic __intrinsic_op vector acos(vector x);\n"; -sb << "__generic __intrinsic_op matrix acos(matrix x);\n"; -sb << "\n"; -sb << "// Test if all components are non-zero (HLSL SM 1.0)\n"; -sb << "__generic __intrinsic_op T all(T x);\n"; -sb << "__generic __intrinsic_op vector all(vector x);\n"; -sb << "__generic __intrinsic_op matrix all(matrix x);\n"; -sb << "\n"; -sb << "// Barrier for writes to all memory spaces (HLSL SM 5.0)\n"; -sb << "__intrinsic_op void AllMemoryBarrier();\n"; -sb << "\n"; -sb << "// Thread-group sync and barrier for writes to all memory spaces (HLSL SM 5.0)\n"; -sb << "__intrinsic_op void AllMemoryBarrierWithGroupSync();\n"; -sb << "\n"; -sb << "// Test if any components is non-zero (HLSL SM 1.0)\n"; -sb << "__generic __intrinsic_op T any(T x);\n"; -sb << "__generic __intrinsic_op vector any(vector x);\n"; -sb << "__generic __intrinsic_op matrix any(matrix x);\n"; -sb << "\n"; -sb << "\n"; -sb << "// Reinterpret bits as a double (HLSL SM 5.0)\n"; -sb << "__intrinsic_op double asdouble(uint lowbits, uint highbits);\n"; -sb << "\n"; -sb << "// Reinterpret bits as a float (HLSL SM 4.0)\n"; -sb << "__intrinsic_op float asfloat( int x);\n"; -sb << "__intrinsic_op float asfloat(uint x);\n"; -sb << "__generic __intrinsic_op vector asfloat(vector< int,N> x);\n"; -sb << "__generic __intrinsic_op vector asfloat(vector x);\n"; -sb << "__generic __intrinsic_op matrix asfloat(matrix< int,N,M> x);\n"; -sb << "__generic __intrinsic_op matrix asfloat(matrix x);\n"; -sb << "\n"; -sb << "\n"; -sb << "// Inverse sine (HLSL SM 1.0)\n"; -sb << "__generic __intrinsic_op T asin(T x);\n"; -sb << "__generic __intrinsic_op vector asin(vector x);\n"; -sb << "__generic __intrinsic_op matrix asin(matrix x);\n"; -sb << "\n"; -sb << "// Reinterpret bits as an int (HLSL SM 4.0)\n"; -sb << "__intrinsic_op int asint(float x);\n"; -sb << "__intrinsic_op int asint(uint x);\n"; -sb << "__generic __intrinsic_op vector asint(vector x);\n"; -sb << "__generic __intrinsic_op vector asint(vector x);\n"; -sb << "__generic __intrinsic_op matrix asint(matrix x);\n"; -sb << "__generic __intrinsic_op matrix asint(matrix x);\n"; -sb << "\n"; -sb << "// Reinterpret bits of double as a uint (HLSL SM 5.0)\n"; -sb << "__intrinsic_op void asuint(double value, out uint lowbits, out uint highbits);\n"; -sb << "\n"; -sb << "// Reinterpret bits as a uint (HLSL SM 4.0)\n"; -sb << "__intrinsic_op uint asuint(float x);\n"; -sb << "__intrinsic_op uint asuint(int x);\n"; -sb << "__generic __intrinsic_op vector asuint(vector x);\n"; -sb << "__generic __intrinsic_op vector asuint(vector x);\n"; -sb << "__generic __intrinsic_op matrix asuint(matrix x);\n"; -sb << "__generic __intrinsic_op matrix asuint(matrix x);\n"; -sb << "\n"; -sb << "// Inverse tangent (HLSL SM 1.0)\n"; -sb << "__generic __intrinsic_op T atan(T x);\n"; -sb << "__generic __intrinsic_op vector atan(vector x);\n"; -sb << "__generic __intrinsic_op matrix atan(matrix x);\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl,\"atan($0,$1)\")\n"; -sb << "__intrinsic_op\n"; -sb << "T atan2(T y, T x);\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl,\"atan($0,$1)\")\n"; -sb << "__intrinsic_op\n"; -sb << "vector atan2(vector y, vector x);\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl,\"atan($0,$1)\")\n"; -sb << "__intrinsic_op\n"; -sb << "matrix atan2(matrix y, matrix x);\n"; -sb << "\n"; -sb << "// Ceiling (HLSL SM 1.0)\n"; -sb << "__generic __intrinsic_op T ceil(T x);\n"; -sb << "__generic __intrinsic_op vector ceil(vector x);\n"; -sb << "__generic __intrinsic_op matrix ceil(matrix x);\n"; -sb << "\n"; -sb << "\n"; -sb << "// Check access status to tiled resource\n"; -sb << "__intrinsic_op bool CheckAccessFullyMapped(uint status);\n"; -sb << "\n"; -sb << "// Clamp (HLSL SM 1.0)\n"; -sb << "__generic __intrinsic_op T clamp(T x, T min, T max);\n"; -sb << "__generic __intrinsic_op vector clamp(vector x, vector min, vector max);\n"; -sb << "__generic __intrinsic_op matrix clamp(matrix x, matrix min, matrix max);\n"; -sb << "\n"; -sb << "// Clip (discard) fragment conditionally\n"; -sb << "__generic __intrinsic_op void clip(T x);\n"; -sb << "__generic __intrinsic_op void clip(vector x);\n"; -sb << "__generic __intrinsic_op void clip(matrix x);\n"; -sb << "\n"; -sb << "// Cosine\n"; -sb << "__generic __intrinsic_op T cos(T x);\n"; -sb << "__generic __intrinsic_op vector cos(vector x);\n"; -sb << "__generic __intrinsic_op matrix cos(matrix x);\n"; -sb << "\n"; -sb << "// Hyperbolic cosine\n"; -sb << "__generic __intrinsic_op T cosh(T x);\n"; -sb << "__generic __intrinsic_op vector cosh(vector x);\n"; -sb << "__generic __intrinsic_op matrix cosh(matrix x);\n"; -sb << "\n"; -sb << "// Population count\n"; -sb << "__intrinsic_op uint countbits(uint value);\n"; -sb << "\n"; -sb << "// Cross product\n"; -sb << "__generic __intrinsic_op vector cross(vector x, vector y);\n"; -sb << "\n"; -sb << "// Convert encoded color\n"; -sb << "__intrinsic_op int4 D3DCOLORtoUBYTE4(float4 x);\n"; -sb << "\n"; -sb << "// Partial-difference derivatives\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, dFdx)\n"; -sb << "__intrinsic_op\n"; -sb << "T ddx(T x);\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, dFdx)\n"; -sb << "__intrinsic_op\n"; -sb << "vector ddx(vector x);\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, dFdx)\n"; -sb << "__intrinsic_op\n"; -sb << "matrix ddx(matrix x);\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__glsl_extension(GL_ARB_derivative_control)\n"; -sb << "__target_intrinsic(glsl, dFdxCoarse)\n"; -sb << "__intrinsic_op\n"; -sb << "T ddx_coarse(T x);\n"; -sb << "__generic\n"; -sb << "__glsl_extension(GL_ARB_derivative_control)\n"; -sb << "__target_intrinsic(glsl, dFdxCoarse)\n"; -sb << "__intrinsic_op\n"; -sb << "vector ddx_coarse(vector x);\n"; -sb << "__generic\n"; -sb << "__glsl_extension(GL_ARB_derivative_control)\n"; -sb << "__target_intrinsic(glsl, dFdxCoarse)\n"; -sb << "__intrinsic_op\n"; -sb << "matrix ddx_coarse(matrix x);\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__glsl_extension(GL_ARB_derivative_control)\n"; -sb << "__target_intrinsic(glsl, dFdxFine)\n"; -sb << "__intrinsic_op\n"; -sb << "T ddx_fine(T x);\n"; -sb << "__generic\n"; -sb << "__glsl_extension(GL_ARB_derivative_control)\n"; -sb << "__target_intrinsic(glsl, dFdxFine)\n"; -sb << "__intrinsic_op\n"; -sb << "vector ddx_fine(vector x);\n"; -sb << "__generic\n"; -sb << "__glsl_extension(GL_ARB_derivative_control)\n"; -sb << "__target_intrinsic(glsl, dFdxFine)\n"; -sb << "__intrinsic_op\n"; -sb << "matrix ddx_fine(matrix x);\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, dFdy)\n"; -sb << "__intrinsic_op\n"; -sb << "T ddy(T x);\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, dFdy)\n"; -sb << "__intrinsic_op\n"; -sb << "vector ddy(vector x);\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, dFdy)\n"; -sb << "__intrinsic_op\n"; -sb << " matrix ddy(matrix x);\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__glsl_extension(GL_ARB_derivative_control)\n"; -sb << "__target_intrinsic(glsl, dFdyCoarse)\n"; -sb << "__intrinsic_op\n"; -sb << "T ddy_coarse(T x);\n"; -sb << "__generic\n"; -sb << "__glsl_extension(GL_ARB_derivative_control)\n"; -sb << "__target_intrinsic(glsl, dFdyCoarse)\n"; -sb << "__intrinsic_op\n"; -sb << "vector ddy_coarse(vector x);\n"; -sb << "__generic\n"; -sb << "__glsl_extension(GL_ARB_derivative_control)\n"; -sb << "__target_intrinsic(glsl, dFdyCoarse)\n"; -sb << "__intrinsic_op\n"; -sb << "matrix ddy_coarse(matrix x);\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__glsl_extension(GL_ARB_derivative_control)\n"; -sb << "__target_intrinsic(glsl, dFdyFine)\n"; -sb << "__intrinsic_op\n"; -sb << "T ddy_fine(T x);\n"; -sb << "__generic\n"; -sb << "__glsl_extension(GL_ARB_derivative_control)\n"; -sb << "__target_intrinsic(glsl, dFdyFine)\n"; -sb << "__intrinsic_op\n"; -sb << "vector ddy_fine(vector x);\n"; -sb << "__generic\n"; -sb << "__glsl_extension(GL_ARB_derivative_control)\n"; -sb << "__target_intrinsic(glsl, dFdyFine)\n"; -sb << "__intrinsic_op\n"; -sb << "matrix ddy_fine(matrix x);\n"; -sb << "\n"; -sb << "\n"; -sb << "// Radians to degrees\n"; -sb << "__generic __intrinsic_op T degrees(T x);\n"; -sb << "__generic __intrinsic_op vector degrees(vector x);\n"; -sb << "__generic __intrinsic_op matrix degrees(matrix x);\n"; -sb << "\n"; -sb << "// Matrix determinant\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T determinant(matrix m);\n"; -sb << "\n"; -sb << "// Barrier for device memory\n"; -sb << "__intrinsic_op void DeviceMemoryBarrier();\n"; -sb << "__intrinsic_op void DeviceMemoryBarrierWithGroupSync();\n"; -sb << "\n"; -sb << "// Vector distance\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T distance(vector x, vector y);\n"; -sb << "\n"; -sb << "// Vector dot product\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T dot(vector x, vector y);\n"; -sb << "\n"; -sb << "// Helper for computing distance terms for lighting (obsolete)\n"; -sb << "\n"; -sb << "__generic __intrinsic_op vector dst(vector x, vector y);\n"; -sb << "\n"; -sb << "// Error message\n"; -sb << "\n"; -sb << "// __intrinsic_op void errorf( string format, ... );\n"; -sb << "\n"; -sb << "// Attribute evaluation\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T EvaluateAttributeAtCentroid(T x);\n"; -sb << "__generic __intrinsic_op vector EvaluateAttributeAtCentroid(vector x);\n"; -sb << "__generic __intrinsic_op matrix EvaluateAttributeAtCentroid(matrix x);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T EvaluateAttributeAtSample(T x, uint sampleindex);\n"; -sb << "__generic __intrinsic_op vector EvaluateAttributeAtSample(vector x, uint sampleindex);\n"; -sb << "__generic __intrinsic_op matrix EvaluateAttributeAtSample(matrix x, uint sampleindex);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T EvaluateAttributeSnapped(T x, int2 offset);\n"; -sb << "__generic __intrinsic_op vector EvaluateAttributeSnapped(vector x, int2 offset);\n"; -sb << "__generic __intrinsic_op matrix EvaluateAttributeSnapped(matrix x, int2 offset);\n"; -sb << "\n"; -sb << "// Base-e exponent\n"; -sb << "__generic __intrinsic_op T exp(T x);\n"; -sb << "__generic __intrinsic_op vector exp(vector x);\n"; -sb << "__generic __intrinsic_op matrix exp(matrix x);\n"; -sb << "\n"; -sb << "// Base-2 exponent\n"; -sb << "__generic __intrinsic_op T exp2(T x);\n"; -sb << "__generic __intrinsic_op vector exp2(vector x);\n"; -sb << "__generic __intrinsic_op matrix exp2(matrix x);\n"; -sb << "\n"; -sb << "// Convert 16-bit float stored in low bits of integer\n"; -sb << "__intrinsic_op float f16tof32(uint value);\n"; -sb << "__generic __intrinsic_op vector f16tof32(vector value);\n"; -sb << "\n"; -sb << "// Convert to 16-bit float stored in low bits of integer\n"; -sb << "__intrinsic_op uint f32tof16(float value);\n"; -sb << "__generic __intrinsic_op vector f32tof16(vector value);\n"; -sb << "\n"; -sb << "// Flip surface normal to face forward, if needed\n"; -sb << "__generic __intrinsic_op vector faceforward(vector n, vector i, vector ng);\n"; -sb << "\n"; -sb << "// Find first set bit starting at high bit and working down\n"; -sb << "__intrinsic_op int firstbithigh(int value);\n"; -sb << "__generic __intrinsic_op vector firstbithigh(vector value);\n"; -sb << "\n"; -sb << "__intrinsic_op uint firstbithigh(uint value);\n"; -sb << "__generic __intrinsic_op vector firstbithigh(vector value);\n"; -sb << "\n"; -sb << "// Find first set bit starting at low bit and working up\n"; -sb << "__intrinsic_op int firstbitlow(int value);\n"; -sb << "__generic __intrinsic_op vector firstbitlow(vector value);\n"; -sb << "\n"; -sb << "__intrinsic_op uint firstbitlow(uint value);\n"; -sb << "__generic __intrinsic_op vector firstbitlow(vector value);\n"; -sb << "\n"; -sb << "// Floor (HLSL SM 1.0)\n"; -sb << "__generic __intrinsic_op T floor(T x);\n"; -sb << "__generic __intrinsic_op vector floor(vector x);\n"; -sb << "__generic __intrinsic_op matrix floor(matrix x);\n"; -sb << "\n"; -sb << "// Fused multiply-add for doubles\n"; -sb << "__intrinsic_op double fma(double a, double b, double c);\n"; -sb << "__generic __intrinsic_op vector fma(vector a, vector b, vector c);\n"; -sb << "__generic __intrinsic_op matrix fma(matrix a, matrix b, matrix c);\n"; -sb << "\n"; -sb << "// Floating point remainder of x/y\n"; -sb << "__generic __intrinsic_op T fmod(T x, T y);\n"; -sb << "__generic __intrinsic_op vector fmod(vector x, vector y);\n"; -sb << "__generic __intrinsic_op matrix fmod(matrix x, matrix y);\n"; -sb << "\n"; -sb << "// Fractional part\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, fract)\n"; -sb << "__intrinsic_op\n"; -sb << "T frac(T x);\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, fract)\n"; -sb << "__intrinsic_op\n"; -sb << "vector frac(vector x);\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, fract)\n"; -sb << "__intrinsic_op\n"; -sb << "matrix frac(matrix x);\n"; -sb << "\n"; -sb << "// Split float into mantissa and exponent\n"; -sb << "__generic __intrinsic_op T frexp(T x, out T exp);\n"; -sb << "__generic __intrinsic_op vector frexp(vector x, out vector exp);\n"; -sb << "__generic __intrinsic_op matrix frexp(matrix x, out matrix exp);\n"; -sb << "\n"; -sb << "// Texture filter width\n"; -sb << "__generic __intrinsic_op T fwidth(T x);\n"; -sb << "__generic __intrinsic_op vector fwidth(vector x);\n"; -sb << "__generic __intrinsic_op matrix fwidth(matrix x);\n"; -sb << "\n"; -sb << "// Get number of samples in render target\n"; -sb << "__intrinsic_op uint GetRenderTargetSampleCount();\n"; -sb << "\n"; -sb << "// Get position of given sample\n"; -sb << "__intrinsic_op float2 GetRenderTargetSamplePosition(int Index);\n"; -sb << "\n"; -sb << "// Group memory barrier\n"; -sb << "__intrinsic_op void GroupMemoryBarrier();\n"; -sb << "__intrinsic_op void GroupMemoryBarrierWithGroupSync();\n"; -sb << "\n"; -sb << "// Atomics\n"; -sb << "__intrinsic_op void InterlockedAdd(in out int dest, int value, out int original_value);\n"; -sb << "__intrinsic_op void InterlockedAdd(in out uint dest, uint value, out uint original_value);\n"; -sb << "\n"; -sb << "__intrinsic_op void InterlockedAnd(in out int dest, int value, out int original_value);\n"; -sb << "__intrinsic_op void InterlockedAnd(in out uint dest, uint value, out uint original_value);\n"; -sb << "\n"; -sb << "__intrinsic_op void InterlockedCompareExchange(in out int dest, int compare_value, int value, out int original_value);\n"; -sb << "__intrinsic_op void InterlockedCompareExchange(in out uint dest, uint compare_value, uint value, out uint original_value);\n"; -sb << "\n"; -sb << "__intrinsic_op void InterlockedCompareStore(in out int dest, int compare_value, int value);\n"; -sb << "__intrinsic_op void InterlockedCompareStore(in out uint dest, uint compare_value, uint value);\n"; -sb << "\n"; -sb << "__intrinsic_op void InterlockedExchange(in out int dest, int value, out int original_value);\n"; -sb << "__intrinsic_op void InterlockedExchange(in out uint dest, uint value, out uint original_value);\n"; -sb << "\n"; -sb << "__intrinsic_op void InterlockedMax(in out int dest, int value, out int original_value);\n"; -sb << "__intrinsic_op void InterlockedMax(in out uint dest, uint value, out uint original_value);\n"; -sb << "\n"; -sb << "__intrinsic_op void InterlockedMin(in out int dest, int value, out int original_value);\n"; -sb << "__intrinsic_op void InterlockedMin(in out uint dest, uint value, out uint original_value);\n"; -sb << "\n"; -sb << "__intrinsic_op void InterlockedOr(in out int dest, int value, out int original_value);\n"; -sb << "__intrinsic_op void InterlockedOr(in out uint dest, uint value, out uint original_value);\n"; -sb << "\n"; -sb << "__intrinsic_op void InterlockedXor(in out int dest, int value, out int original_value);\n"; -sb << "__intrinsic_op void InterlockedXor(in out uint dest, uint value, out uint original_value);\n"; -sb << "\n"; -sb << "// Is floating-point value finite?\n"; -sb << "__generic __intrinsic_op bool isfinite(T x);\n"; -sb << "__generic __intrinsic_op vector isfinite(vector x);\n"; -sb << "__generic __intrinsic_op matrix isfinite(matrix x);\n"; -sb << "\n"; -sb << "// Is floating-point value infinite?\n"; -sb << "__generic __intrinsic_op bool isinf(T x);\n"; -sb << "__generic __intrinsic_op vector isinf(vector x);\n"; -sb << "__generic __intrinsic_op matrix isinf(matrix x);\n"; -sb << "\n"; -sb << "// Is floating-point value not-a-number?\n"; -sb << "__generic __intrinsic_op bool isnan(T x);\n"; -sb << "__generic __intrinsic_op vector isnan(vector x);\n"; -sb << "__generic __intrinsic_op matrix isnan(matrix x);\n"; -sb << "\n"; -sb << "// Construct float from mantissa and exponent\n"; -sb << "__generic __intrinsic_op T ldexp(T x, T exp);\n"; -sb << "__generic __intrinsic_op vector ldexp(vector x, vector exp);\n"; -sb << "__generic __intrinsic_op matrix ldexp(matrix x, matrix exp);\n"; -sb << "\n"; -sb << "// Vector length\n"; -sb << "__generic __intrinsic_op T length(vector x);\n"; -sb << "\n"; -sb << "// Linear interpolation\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, mix)\n"; -sb << "__intrinsic_op\n"; -sb << "T lerp(T x, T y, T s);\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, mix)\n"; -sb << "__intrinsic_op\n"; -sb << "vector lerp(vector x, vector y, vector s);\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, mix)\n"; -sb << "__intrinsic_op\n"; -sb << "matrix lerp(matrix x, matrix y, matrix s);\n"; -sb << "\n"; -sb << "// Legacy lighting function (obsolete)\n"; -sb << "__intrinsic_op float4 lit(float n_dot_l, float n_dot_h, float m);\n"; -sb << "\n"; -sb << "// Base-e logarithm\n"; -sb << "__generic __intrinsic_op T log(T x);\n"; -sb << "__generic __intrinsic_op vector log(vector x);\n"; -sb << "__generic __intrinsic_op matrix log(matrix x);\n"; -sb << "\n"; -sb << "// Base-10 logarithm\n"; -sb << "__generic __intrinsic_op T log10(T x);\n"; -sb << "__generic __intrinsic_op vector log10(vector x);\n"; -sb << "__generic __intrinsic_op matrix log10(matrix x);\n"; -sb << "\n"; -sb << "// Base-2 logarithm\n"; -sb << "__generic __intrinsic_op T log2(T x);\n"; -sb << "__generic __intrinsic_op vector log2(vector x);\n"; -sb << "__generic __intrinsic_op matrix log2(matrix x);\n"; -sb << "\n"; -sb << "// multiply-add\n"; -sb << "__generic __intrinsic_op T mad(T mvalue, T avalue, T bvalue);\n"; -sb << "__generic __intrinsic_op vector mad(vector mvalue, vector avalue, vector bvalue);\n"; -sb << "__generic __intrinsic_op matrix mad(matrix mvalue, matrix avalue, matrix bvalue);\n"; -sb << "\n"; -sb << "// maximum\n"; -sb << "__generic __intrinsic_op T max(T x, T y);\n"; -sb << "__generic __intrinsic_op vector max(vector x, vector y);\n"; -sb << "__generic __intrinsic_op matrix max(matrix x, matrix y);\n"; -sb << "\n"; -sb << "// minimum\n"; -sb << "__generic __intrinsic_op T min(T x, T y);\n"; -sb << "__generic __intrinsic_op vector min(vector x, vector y);\n"; -sb << "__generic __intrinsic_op matrix min(matrix x, matrix y);\n"; -sb << "\n"; -sb << "// split into integer and fractional parts (both with same sign)\n"; -sb << "__generic __intrinsic_op T modf(T x, out T ip);\n"; -sb << "__generic __intrinsic_op vector modf(vector x, out vector ip);\n"; -sb << "__generic __intrinsic_op matrix modf(matrix x, out matrix ip);\n"; -sb << "\n"; -sb << "// msad4 (whatever that is)\n"; -sb << "__intrinsic_op uint4 msad4(uint reference, uint2 source, uint4 accum);\n"; -sb << "\n"; -sb << "// General inner products\n"; -sb << "\n"; -sb << "// scalar-scalar\n"; -sb << "__generic __intrinsic_op T mul(T x, T y);\n"; -sb << "\n"; -sb << "// scalar-vector and vector-scalar\n"; -sb << "__generic __intrinsic_op vector mul(vector x, T y);\n"; -sb << "__generic __intrinsic_op vector mul(T x, vector y);\n"; -sb << "\n"; -sb << "// scalar-matrix and matrix-scalar\n"; -sb << "__generic __intrinsic_op matrix mul(matrix x, T y);\n"; -sb << "__generic __intrinsic_op matrix mul(T x, matrix y);\n"; -sb << "\n"; -sb << "// vector-vector (dot product)\n"; -sb << "__generic __intrinsic_op(dot) T mul(vector x, vector y);\n"; -sb << "\n"; -sb << "// vector-matrix\n"; -sb << "__generic __intrinsic_op(mulVectorMatrix) vector mul(vector x, matrix y);\n"; -sb << "\n"; -sb << "// matrix-vector\n"; -sb << "__generic __intrinsic_op(mulMatrixVector) vector mul(matrix x, vector y);\n"; -sb << "\n"; -sb << "// matrix-matrix\n"; -sb << "__generic __intrinsic_op(mulMatrixMatrix) matrix mul(matrix x, matrix y);\n"; -sb << "\n"; -sb << "// noise (deprecated)\n"; -sb << "__intrinsic_op float noise(float x);\n"; -sb << "__generic __intrinsic_op float noise(vector x);\n"; -sb << "\n"; -sb << "// Normalize a vector\n"; -sb << "__generic __intrinsic_op vector normalize(vector x);\n"; -sb << "\n"; -sb << "// Raise to a power\n"; -sb << "__generic __intrinsic_op T pow(T x, T y);\n"; -sb << "__generic __intrinsic_op vector pow(vector x, vector y);\n"; -sb << "__generic __intrinsic_op matrix pow(matrix x, matrix y);\n"; -sb << "\n"; -sb << "// Output message\n"; -sb << "\n"; -sb << "// __intrinsic_op void printf( string format, ... );\n"; -sb << "\n"; -sb << "// Tessellation factor fixup routines\n"; -sb << "\n"; -sb << "__intrinsic_op void Process2DQuadTessFactorsAvg(\n"; -sb << " in float4 RawEdgeFactors,\n"; -sb << " in float2 InsideScale,\n"; -sb << " out float4 RoundedEdgeTessFactors,\n"; -sb << " out float2 RoundedInsideTessFactors,\n"; -sb << " out float2 UnroundedInsideTessFactors);\n"; -sb << "\n"; -sb << "__intrinsic_op void Process2DQuadTessFactorsMax(\n"; -sb << " in float4 RawEdgeFactors,\n"; -sb << " in float2 InsideScale,\n"; -sb << " out float4 RoundedEdgeTessFactors,\n"; -sb << " out float2 RoundedInsideTessFactors,\n"; -sb << " out float2 UnroundedInsideTessFactors);\n"; -sb << "\n"; -sb << "__intrinsic_op void Process2DQuadTessFactorsMin(\n"; -sb << " in float4 RawEdgeFactors,\n"; -sb << " in float2 InsideScale,\n"; -sb << " out float4 RoundedEdgeTessFactors,\n"; -sb << " out float2 RoundedInsideTessFactors,\n"; -sb << " out float2 UnroundedInsideTessFactors);\n"; -sb << "\n"; -sb << "__intrinsic_op void ProcessIsolineTessFactors(\n"; -sb << " in float RawDetailFactor,\n"; -sb << " in float RawDensityFactor,\n"; -sb << " out float RoundedDetailFactor,\n"; -sb << " out float RoundedDensityFactor);\n"; -sb << "\n"; -sb << "__intrinsic_op void ProcessQuadTessFactorsAvg(\n"; -sb << " in float4 RawEdgeFactors,\n"; -sb << " in float InsideScale,\n"; -sb << " out float4 RoundedEdgeTessFactors,\n"; -sb << " out float2 RoundedInsideTessFactors,\n"; -sb << " out float2 UnroundedInsideTessFactors);\n"; -sb << "\n"; -sb << "__intrinsic_op void ProcessQuadTessFactorsMax(\n"; -sb << " in float4 RawEdgeFactors,\n"; -sb << " in float InsideScale,\n"; -sb << " out float4 RoundedEdgeTessFactors,\n"; -sb << " out float2 RoundedInsideTessFactors,\n"; -sb << " out float2 UnroundedInsideTessFactors);\n"; -sb << "\n"; -sb << "__intrinsic_op void ProcessQuadTessFactorsMin(\n"; -sb << " in float4 RawEdgeFactors,\n"; -sb << " in float InsideScale,\n"; -sb << " out float4 RoundedEdgeTessFactors,\n"; -sb << " out float2 RoundedInsideTessFactors,\n"; -sb << " out float2 UnroundedInsideTessFactors);\n"; -sb << "\n"; -sb << "__intrinsic_op void ProcessTriTessFactorsAvg(\n"; -sb << " in float3 RawEdgeFactors,\n"; -sb << " in float InsideScale,\n"; -sb << " out float3 RoundedEdgeTessFactors,\n"; -sb << " out float RoundedInsideTessFactor,\n"; -sb << " out float UnroundedInsideTessFactor);\n"; -sb << "\n"; -sb << "__intrinsic_op void ProcessTriTessFactorsMax(\n"; -sb << " in float3 RawEdgeFactors,\n"; -sb << " in float InsideScale,\n"; -sb << " out float3 RoundedEdgeTessFactors,\n"; -sb << " out float RoundedInsideTessFactor,\n"; -sb << " out float UnroundedInsideTessFactor);\n"; -sb << "\n"; -sb << "__intrinsic_op void ProcessTriTessFactorsMin(\n"; -sb << " in float3 RawEdgeFactors,\n"; -sb << " in float InsideScale,\n"; -sb << " out float3 RoundedEdgeTessFactors,\n"; -sb << " out float RoundedInsideTessFactors,\n"; -sb << " out float UnroundedInsideTessFactors);\n"; -sb << "\n"; -sb << "// Degrees to radians\n"; -sb << "__generic __intrinsic_op T radians(T x);\n"; -sb << "__generic __intrinsic_op vector radians(vector x);\n"; -sb << "__generic __intrinsic_op matrix radians(matrix x);\n"; -sb << "\n"; -sb << "// Approximate reciprocal\n"; -sb << "__generic __intrinsic_op T rcp(T x);\n"; -sb << "__generic __intrinsic_op vector rcp(vector x);\n"; -sb << "__generic __intrinsic_op matrix rcp(matrix x);\n"; -sb << "\n"; -sb << "// Reflect incident vector across plane with given normal\n"; -sb << "__generic\n"; -sb << "__intrinsic_op\n"; -sb << "vector reflect(vector i, vector n);\n"; -sb << "\n"; -sb << "// Refract incident vector given surface normal and index of refraction\n"; -sb << "__generic\n"; -sb << "__intrinsic_op\n"; -sb << "vector refract(vector i, vector n, float eta);\n"; -sb << "\n"; -sb << "// Reverse order of bits\n"; -sb << "__intrinsic_op uint reversebits(uint value);\n"; -sb << "__generic vector reversebits(vector value);\n"; -sb << "\n"; -sb << "// Round-to-nearest\n"; -sb << "__generic __intrinsic_op T round(T x);\n"; -sb << "__generic __intrinsic_op vector round(vector x);\n"; -sb << "__generic __intrinsic_op matrix round(matrix x);\n"; -sb << "\n"; -sb << "// Reciprocal of square root\n"; -sb << "__generic __intrinsic_op T rsqrt(T x);\n"; -sb << "__generic __intrinsic_op vector rsqrt(vector x);\n"; -sb << "__generic __intrinsic_op matrix rsqrt(matrix x);\n"; -sb << "\n"; -sb << "// Clamp value to [0,1] range\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, \"clamp($0, 0, 1)\") __intrinsic_op\n"; -sb << "T saturate(T x);\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, \"clamp($0, 0, 1)\") __intrinsic_op\n"; -sb << "vector saturate(vector x);\n"; -sb << "\n"; -sb << "__generic\n"; -sb << "__target_intrinsic(glsl, \"clamp($0, 0, 1)\") __intrinsic_op\n"; -sb << "matrix saturate(matrix x);\n"; -sb << "\n"; -sb << "\n"; -sb << "// Extract sign of value\n"; -sb << "__generic __intrinsic_op int sign(T x);\n"; -sb << "__generic __intrinsic_op vector sign(vector x);\n"; -sb << "__generic __intrinsic_op matrix sign(matrix x);\n"; -sb << "\n"; -sb << "\n"; -sb << "// Sine\n"; -sb << "__generic __intrinsic_op T sin(T x);\n"; -sb << "__generic __intrinsic_op vector sin(vector x);\n"; -sb << "__generic __intrinsic_op matrix sin(matrix x);\n"; -sb << "\n"; -sb << "// Sine and cosine\n"; -sb << "__generic __intrinsic_op void sincos(T x, out T s, out T c);\n"; -sb << "__generic __intrinsic_op void sincos(vector x, out vector s, out vector c);\n"; -sb << "__generic __intrinsic_op void sincos(matrix x, out matrix s, out matrix c);\n"; -sb << "\n"; -sb << "// Hyperbolic Sine\n"; -sb << "__generic __intrinsic_op T sinh(T x);\n"; -sb << "__generic __intrinsic_op vector sinh(vector x);\n"; -sb << "__generic __intrinsic_op matrix sinh(matrix x);\n"; -sb << "\n"; -sb << "// Smooth step (Hermite interpolation)\n"; -sb << "__generic __intrinsic_op T smoothstep(T min, T max, T x);\n"; -sb << "__generic __intrinsic_op vector smoothstep(vector min, vector max, vector x);\n"; -sb << "__generic __intrinsic_op matrix smoothstep(matrix min, matrix max, matrix x);\n"; -sb << "\n"; -sb << "// Square root\n"; -sb << "__generic __intrinsic_op T sqrt(T x);\n"; -sb << "__generic __intrinsic_op vector sqrt(vector x);\n"; -sb << "__generic __intrinsic_op matrix sqrt(matrix x);\n"; -sb << "\n"; -sb << "// Step function\n"; -sb << "__generic __intrinsic_op T step(T y, T x);\n"; -sb << "__generic __intrinsic_op vector step(vector y, vector x);\n"; -sb << "__generic __intrinsic_op matrix step(matrix y, matrix x);\n"; -sb << "\n"; -sb << "// Tangent\n"; -sb << "__generic __intrinsic_op T tan(T x);\n"; -sb << "__generic __intrinsic_op vector tan(vector x);\n"; -sb << "__generic __intrinsic_op matrix tan(matrix x);\n"; -sb << "\n"; -sb << "// Hyperbolic tangent\n"; -sb << "__generic __intrinsic_op T tanh(T x);\n"; -sb << "__generic __intrinsic_op vector tanh(vector x);\n"; -sb << "__generic __intrinsic_op matrix tanh(matrix x);\n"; -sb << "\n"; -sb << "// Legacy texture-fetch operations\n"; -sb << "\n"; -sb << "/*\n"; -sb << "__intrinsic_op float4 tex1D(sampler1D s, float t);\n"; -sb << "__intrinsic_op float4 tex1D(sampler1D s, float t, float ddx, float ddy);\n"; -sb << "__intrinsic_op float4 tex1Dbias(sampler1D s, float4 t);\n"; -sb << "__intrinsic_op float4 tex1Dgrad(sampler1D s, float t, float ddx, float ddy);\n"; -sb << "__intrinsic_op float4 tex1Dlod(sampler1D s, float4 t);\n"; -sb << "__intrinsic_op float4 tex1Dproj(sampler1D s, float4 t);\n"; -sb << "\n"; -sb << "__intrinsic_op float4 tex2D(sampler2D s, float2 t);\n"; -sb << "__intrinsic_op float4 tex2D(sampler2D s, float2 t, float2 ddx, float2 ddy);\n"; -sb << "__intrinsic_op float4 tex2Dbias(sampler2D s, float4 t);\n"; -sb << "__intrinsic_op float4 tex2Dgrad(sampler2D s, float2 t, float2 ddx, float2 ddy);\n"; -sb << "__intrinsic_op float4 tex2Dlod(sampler2D s, float4 t);\n"; -sb << "__intrinsic_op float4 tex2Dproj(sampler2D s, float4 t);\n"; -sb << "\n"; -sb << "__intrinsic_op float4 tex3D(sampler3D s, float3 t);\n"; -sb << "__intrinsic_op float4 tex3D(sampler3D s, float3 t, float3 ddx, float3 ddy);\n"; -sb << "__intrinsic_op float4 tex3Dbias(sampler3D s, float4 t);\n"; -sb << "__intrinsic_op float4 tex3Dgrad(sampler3D s, float3 t, float3 ddx, float3 ddy);\n"; -sb << "__intrinsic_op float4 tex3Dlod(sampler3D s, float4 t);\n"; -sb << "__intrinsic_op float4 tex3Dproj(sampler3D s, float4 t);\n"; -sb << "\n"; -sb << "__intrinsic_op float4 texCUBE(samplerCUBE s, float3 t);\n"; -sb << "__intrinsic_op float4 texCUBE(samplerCUBE s, float3 t, float3 ddx, float3 ddy);\n"; -sb << "__intrinsic_op float4 texCUBEbias(samplerCUBE s, float4 t);\n"; -sb << "__intrinsic_op float4 texCUBEgrad(samplerCUBE s, float3 t, float3 ddx, float3 ddy);\n"; -sb << "__intrinsic_op float4 texCUBElod(samplerCUBE s, float4 t);\n"; -sb << "__intrinsic_op float4 texCUBEproj(samplerCUBE s, float4 t);\n"; -sb << "*/\n"; -sb << "\n"; -sb << "// Matrix transpose\n"; -sb << "__generic __intrinsic_op matrix transpose(matrix x);\n"; -sb << "\n"; -sb << "// Truncate to integer\n"; -sb << "__generic __intrinsic_op T trunc(T x);\n"; -sb << "__generic __intrinsic_op vector trunc(vector x);\n"; -sb << "__generic __intrinsic_op matrix trunc(matrix x);\n"; -sb << "\n"; -sb << "// Shader model 6.0 stuff\n"; -sb << "\n"; -sb << "__intrinsic_op uint GlobalOrderedCountIncrement(uint countToAppendForThisLane);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T QuadReadLaneAt(T sourceValue, int quadLaneID);\n"; -sb << "__generic __intrinsic_op vector QuadReadLaneAt(vector sourceValue, int quadLaneID);\n"; -sb << "__generic __intrinsic_op matrix QuadReadLaneAt(matrix sourceValue, int quadLaneID);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T QuadSwapX(T localValue);\n"; -sb << "__generic __intrinsic_op vector QuadSwapX(vector localValue);\n"; -sb << "__generic __intrinsic_op matrix QuadSwapX(matrix localValue);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T QuadSwapY(T localValue);\n"; -sb << "__generic __intrinsic_op vector QuadSwapY(vector localValue);\n"; -sb << "__generic __intrinsic_op matrix QuadSwapY(matrix localValue);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T WaveAllBitAnd(T expr);\n"; -sb << "__generic __intrinsic_op vector WaveAllBitAnd(vector expr);\n"; -sb << "__generic __intrinsic_op matrix WaveAllBitAnd(matrix expr);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T WaveAllBitOr(T expr);\n"; -sb << "__generic __intrinsic_op vector WaveAllBitOr(vector expr);\n"; -sb << "__generic __intrinsic_op matrix WaveAllBitOr(matrix expr);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T WaveAllBitXor(T expr);\n"; -sb << "__generic __intrinsic_op vector WaveAllBitXor(vector expr);\n"; -sb << "__generic __intrinsic_op matrix WaveAllBitXor(matrix expr);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T WaveAllMax(T expr);\n"; -sb << "__generic __intrinsic_op vector WaveAllMax(vector expr);\n"; -sb << "__generic __intrinsic_op matrix WaveAllMax(matrix expr);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T WaveAllMin(T expr);\n"; -sb << "__generic __intrinsic_op vector WaveAllMin(vector expr);\n"; -sb << "__generic __intrinsic_op matrix WaveAllMin(matrix expr);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T WaveAllProduct(T expr);\n"; -sb << "__generic __intrinsic_op vector WaveAllProduct(vector expr);\n"; -sb << "__generic __intrinsic_op matrix WaveAllProduct(matrix expr);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T WaveAllSum(T expr);\n"; -sb << "__generic __intrinsic_op vector WaveAllSum(vector expr);\n"; -sb << "__generic __intrinsic_op matrix WaveAllSum(matrix expr);\n"; -sb << "\n"; -sb << "__intrinsic_op bool WaveAllEqual(bool expr);\n"; -sb << "__intrinsic_op bool WaveAllTrue(bool expr);\n"; -sb << "__intrinsic_op bool WaveAnyTrue(bool expr);\n"; -sb << "\n"; -sb << "uint64_t WaveBallot(bool expr);\n"; -sb << "\n"; -sb << "uint WaveGetLaneCount();\n"; -sb << "uint WaveGetLaneIndex();\n"; -sb << "uint WaveGetOrderedIndex();\n"; -sb << "\n"; -sb << "bool WaveIsHelperLane();\n"; -sb << "\n"; -sb << "bool WaveOnce();\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T WavePrefixProduct(T expr);\n"; -sb << "__generic __intrinsic_op vector WavePrefixProduct(vector expr);\n"; -sb << "__generic __intrinsic_op matrix WavePrefixProduct(matrix expr);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T WavePrefixSum(T expr);\n"; -sb << "__generic __intrinsic_op vector WavePrefixSum(vector expr);\n"; -sb << "__generic __intrinsic_op matrix WavePrefixSum(matrix expr);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T WaveReadFirstLane(T expr);\n"; -sb << "__generic __intrinsic_op vector WaveReadFirstLane(vector expr);\n"; -sb << "__generic __intrinsic_op matrix WaveReadFirstLane(matrix expr);\n"; -sb << "\n"; -sb << "__generic __intrinsic_op T WaveReadLaneAt(T expr, int laneIndex);\n"; -sb << "__generic __intrinsic_op vector WaveReadLaneAt(vector expr, int laneIndex);\n"; -sb << "__generic __intrinsic_op matrix WaveReadLaneAt(matrix expr, int laneIndex);\n"; -sb << "\n"; -sb << "// `typedef`s to help with the fact that HLSL has been sorta-kinda case insensitive at various points\n"; -sb << "typedef Texture2D texture2D;\n"; -sb << "\n"; -sb << ""; - - -// Component-wise multiplication ops -for(auto op : binaryOps) -{ - switch (op.opCode) - { - default: - continue; - - case kIROp_Mul: - case kIRPseudoOp_MulAssign: - break; - } - - for (auto type : kBaseTypes) - { - if ((type.flags & op.flags) == 0) - continue; - - char const* leftType = type.name; - char const* rightType = leftType; - char const* resultType = leftType; - - char const* leftQual = ""; - if(op.flags & ASSIGNMENT) leftQual = "in out "; - - sb << "__generic "; - sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n"; - } -} - -// - -// Buffer types - -static const struct { - char const* name; - SlangResourceAccess access; -} kBaseBufferAccessLevels[] = { - { "", SLANG_RESOURCE_ACCESS_READ }, - { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE }, - { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED }, -}; -static const int kBaseBufferAccessLevelCount = sizeof(kBaseBufferAccessLevels) / sizeof(kBaseBufferAccessLevels[0]); - -for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa) -{ - - sb << "__generic __magic_type(Texture, "; - sb << ResourceType::makeFlavor(ResourceType::Shape::ShapeBuffer, kBaseBufferAccessLevels[aa].access); - sb << ") struct "; - sb << kBaseBufferAccessLevels[aa].name; - sb << "Buffer {\n"; - - sb << "__intrinsic_op void GetDimensions(out uint dim);\n"; - - sb << "__target_intrinsic(glsl, \"texelFetch($P, $0)$z\")\n"; - sb << "__intrinsic_op T Load(int location);\n"; - - sb << "__intrinsic_op T Load(int location, out uint status);\n"; - - sb << "__target_intrinsic(glsl, \"texelFetch($P, int($0))$z\")\n"; - sb << "__intrinsic_op __subscript(uint index) -> T"; - - if (kBaseBufferAccessLevels[aa].access != SLANG_RESOURCE_ACCESS_READ) - { - sb << " { get; set; }\n"; - } - else - { - sb << ";\n"; - } - - sb << "};\n"; -} - -sb << ""; diff --git a/source/slang/hlsl.meta.slang.h b/source/slang/hlsl.meta.slang.h new file mode 100644 index 000000000..49254ac60 --- /dev/null +++ b/source/slang/hlsl.meta.slang.h @@ -0,0 +1,1089 @@ +sb << "// Slang HLSL compatibility library\n"; +sb << "\n"; +sb << "typedef uint UINT;\n"; +sb << "\n"; +sb << "__generic __magic_type(HLSLAppendStructuredBufferType) struct AppendStructuredBuffer\n"; +sb << "{\n"; +sb << " __intrinsic_op void Append(T value);\n"; +sb << "\n"; +sb << " __intrinsic_op void GetDimensions(\n"; +sb << " out uint numStructs,\n"; +sb << " out uint stride);\n"; +sb << "};\n"; +sb << "\n"; +sb << "__magic_type(HLSLByteAddressBufferType) struct ByteAddressBuffer\n"; +sb << "{\n"; +sb << " __intrinsic_op void GetDimensions(\n"; +sb << " out uint dim);\n"; +sb << "\n"; +sb << " __intrinsic_op uint Load(int location);\n"; +sb << " __intrinsic_op uint Load(int location, out uint status);\n"; +sb << "\n"; +sb << " __intrinsic_op uint2 Load2(int location);\n"; +sb << " __intrinsic_op uint2 Load2(int location, out uint status);\n"; +sb << "\n"; +sb << " __intrinsic_op uint3 Load3(int location);\n"; +sb << " __intrinsic_op uint3 Load3(int location, out uint status);\n"; +sb << "\n"; +sb << " __intrinsic_op uint4 Load4(int location);\n"; +sb << " __intrinsic_op uint4 Load4(int location, out uint status);\n"; +sb << "};\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__magic_type(HLSLStructuredBufferType)\n"; +sb << "__intrinsic_type("; + + // TODO: we really need a simple way to write an "expression splice" + sb << kIROp_structuredBufferType; +sb << ")\n"; +sb << "struct StructuredBuffer\n"; +sb << "{\n"; +sb << " __intrinsic_op void GetDimensions(\n"; +sb << " out uint numStructs,\n"; +sb << " out uint stride);\n"; +sb << "\n"; +sb << " __intrinsic_op T Load(int location);\n"; +sb << " __intrinsic_op T Load(int location, out uint status);\n"; +sb << "\n"; +sb << " __intrinsic_op(bufferLoad)\n"; +sb << " __subscript(uint index) -> T;\n"; +sb << "};\n"; +sb << "\n"; +sb << "__generic __magic_type(HLSLConsumeStructuredBufferType) struct ConsumeStructuredBuffer\n"; +sb << "{\n"; +sb << " __intrinsic_op T Consume();\n"; +sb << "\n"; +sb << " __intrinsic_op void GetDimensions(\n"; +sb << " out uint numStructs,\n"; +sb << " out uint stride);\n"; +sb << "};\n"; +sb << "\n"; +sb << "__generic __magic_type(HLSLInputPatchType) struct InputPatch\n"; +sb << "{\n"; +sb << " __intrinsic_op __subscript(uint index) -> T;\n"; +sb << "};\n"; +sb << "\n"; +sb << "__generic __magic_type(HLSLOutputPatchType) struct OutputPatch\n"; +sb << "{\n"; +sb << " __intrinsic_op __subscript(uint index) -> T { set; }\n"; +sb << "};\n"; +sb << "\n"; +sb << "__magic_type(HLSLRWByteAddressBufferType) struct RWByteAddressBuffer\n"; +sb << "{\n"; +sb << " // Note(tfoley): supports alll operations from `ByteAddressBuffer`\n"; +sb << " // TODO(tfoley): can this be made a sub-type?\n"; +sb << "\n"; +sb << " __intrinsic_op void GetDimensions(\n"; +sb << " out uint dim);\n"; +sb << "\n"; +sb << " __intrinsic_op uint Load(int location);\n"; +sb << " __intrinsic_op uint Load(int location, out uint status);\n"; +sb << "\n"; +sb << " __intrinsic_op uint2 Load2(int location);\n"; +sb << " __intrinsic_op uint2 Load2(int location, out uint status);\n"; +sb << "\n"; +sb << " __intrinsic_op uint3 Load3(int location);\n"; +sb << " __intrinsic_op uint3 Load3(int location, out uint status);\n"; +sb << "\n"; +sb << " __intrinsic_op uint4 Load4(int location);\n"; +sb << " __intrinsic_op uint4 Load4(int location, out uint status);\n"; +sb << "\n"; +sb << " // Added operations:\n"; +sb << "\n"; +sb << " __intrinsic_op void InterlockedAdd(\n"; +sb << " UINT dest,\n"; +sb << " UINT value,\n"; +sb << " out UINT original_value);\n"; +sb << " __intrinsic_op void InterlockedAdd(\n"; +sb << " UINT dest,\n"; +sb << " UINT value);\n"; +sb << "\n"; +sb << " __intrinsic_op void InterlockedAnd(\n"; +sb << " UINT dest,\n"; +sb << " UINT value,\n"; +sb << " out UINT original_value);\n"; +sb << " __intrinsic_op void InterlockedAnd(\n"; +sb << " UINT dest,\n"; +sb << " UINT value);\n"; +sb << "\n"; +sb << " __intrinsic_op void InterlockedCompareExchange(\n"; +sb << " UINT dest,\n"; +sb << " UINT compare_value,\n"; +sb << " UINT value,\n"; +sb << " out UINT original_value);\n"; +sb << " __intrinsic_op void InterlockedCompareExchange(\n"; +sb << " UINT dest,\n"; +sb << " UINT compare_value,\n"; +sb << " UINT value);\n"; +sb << "\n"; +sb << " __intrinsic_op void InterlockedCompareStore(\n"; +sb << " UINT dest,\n"; +sb << " UINT compare_value,\n"; +sb << " UINT value);\n"; +sb << " __intrinsic_op void InterlockedCompareStore(\n"; +sb << " UINT dest,\n"; +sb << " UINT compare_value);\n"; +sb << "\n"; +sb << " __intrinsic_op void InterlockedExchange(\n"; +sb << " UINT dest,\n"; +sb << " UINT value,\n"; +sb << " out UINT original_value);\n"; +sb << " __intrinsic_op void InterlockedExchange(\n"; +sb << " UINT dest,\n"; +sb << " UINT value);\n"; +sb << "\n"; +sb << " __intrinsic_op void InterlockedMax(\n"; +sb << " UINT dest,\n"; +sb << " UINT value,\n"; +sb << " out UINT original_value);\n"; +sb << " __intrinsic_op void InterlockedMax(\n"; +sb << " UINT dest,\n"; +sb << " UINT value);\n"; +sb << "\n"; +sb << " __intrinsic_op void InterlockedMin(\n"; +sb << " UINT dest,\n"; +sb << " UINT value,\n"; +sb << " out UINT original_value);\n"; +sb << " __intrinsic_op void InterlockedMin(\n"; +sb << " UINT dest,\n"; +sb << " UINT value);\n"; +sb << "\n"; +sb << " __intrinsic_op void InterlockedOr(\n"; +sb << " UINT dest,\n"; +sb << " UINT value,\n"; +sb << " out UINT original_value);\n"; +sb << " __intrinsic_op void InterlockedOr(\n"; +sb << " UINT dest,\n"; +sb << " UINT value);\n"; +sb << "\n"; +sb << " __intrinsic_op void InterlockedXor(\n"; +sb << " UINT dest,\n"; +sb << " UINT value,\n"; +sb << " out UINT original_value);\n"; +sb << " __intrinsic_op void InterlockedXor(\n"; +sb << " UINT dest,\n"; +sb << " UINT value);\n"; +sb << "\n"; +sb << " __intrinsic_op void Store(\n"; +sb << " uint address,\n"; +sb << " uint value);\n"; +sb << "\n"; +sb << " __intrinsic_op void Store2(\n"; +sb << " uint address,\n"; +sb << " uint2 value);\n"; +sb << "\n"; +sb << " __intrinsic_op void Store3(\n"; +sb << " uint address,\n"; +sb << " uint3 value);\n"; +sb << "\n"; +sb << " __intrinsic_op void Store4(\n"; +sb << " uint address,\n"; +sb << " uint4 value);\n"; +sb << "};\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__magic_type(HLSLRWStructuredBufferType)\n"; +sb << "__intrinsic_type("; + + // TODO: we really need a simple way to write an "expression splice" + sb << kIROp_readWriteStructuredBufferType; +sb << ")\n"; +sb << "struct RWStructuredBuffer\n"; +sb << "{\n"; +sb << " __intrinsic_op uint DecrementCounter();\n"; +sb << "\n"; +sb << " __intrinsic_op void GetDimensions(\n"; +sb << " out uint numStructs,\n"; +sb << " out uint stride);\n"; +sb << "\n"; +sb << " __intrinsic_op void IncrementCounter();\n"; +sb << "\n"; +sb << " __intrinsic_op T Load(int location);\n"; +sb << " __intrinsic_op T Load(int location, out uint status);\n"; +sb << "\n"; +sb << "\t__intrinsic_op\n"; +sb << "\t__subscript(uint index) -> T\n"; +sb << "\t{\n"; +sb << "\t\t__intrinsic_op(bufferLoad)\n"; +sb << "\t\tget;\n"; +sb << "\n"; +sb << "\t\t__intrinsic_op(bufferStore)\n"; +sb << "\t\tset;\n"; +sb << "\t}\n"; +sb << "};\n"; +sb << "\n"; +sb << "__generic __magic_type(HLSLPointStreamType) struct PointStream\n"; +sb << "{\n"; +sb << " void Append(T value);\n"; +sb << " void RestartStrip();\n"; +sb << "};\n"; +sb << "\n"; +sb << "__generic __magic_type(HLSLLineStreamType) struct LineStream\n"; +sb << "{\n"; +sb << " void Append(T value);\n"; +sb << " void RestartStrip();\n"; +sb << "};\n"; +sb << "\n"; +sb << "__generic __magic_type(HLSLTriangleStreamType) struct TriangleStream\n"; +sb << "{\n"; +sb << " void Append(T value);\n"; +sb << " void RestartStrip();\n"; +sb << "};\n"; +sb << "\n"; +sb << "// Note(tfoley): Trying to systematically add all the HLSL builtins\n"; +sb << "\n"; +sb << "// Try to terminate the current draw or dispatch call (HLSL SM 4.0)\n"; +sb << "__intrinsic_op void abort();\n"; +sb << "\n"; +sb << "// Absolute value (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T abs(T x);\n"; +sb << "__generic __intrinsic_op vector abs(vector x);\n"; +sb << "__generic __intrinsic_op matrix abs(matrix x);\n"; +sb << "\n"; +sb << "// Inverse cosine (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T acos(T x);\n"; +sb << "__generic __intrinsic_op vector acos(vector x);\n"; +sb << "__generic __intrinsic_op matrix acos(matrix x);\n"; +sb << "\n"; +sb << "// Test if all components are non-zero (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T all(T x);\n"; +sb << "__generic __intrinsic_op vector all(vector x);\n"; +sb << "__generic __intrinsic_op matrix all(matrix x);\n"; +sb << "\n"; +sb << "// Barrier for writes to all memory spaces (HLSL SM 5.0)\n"; +sb << "__intrinsic_op void AllMemoryBarrier();\n"; +sb << "\n"; +sb << "// Thread-group sync and barrier for writes to all memory spaces (HLSL SM 5.0)\n"; +sb << "__intrinsic_op void AllMemoryBarrierWithGroupSync();\n"; +sb << "\n"; +sb << "// Test if any components is non-zero (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T any(T x);\n"; +sb << "__generic __intrinsic_op vector any(vector x);\n"; +sb << "__generic __intrinsic_op matrix any(matrix x);\n"; +sb << "\n"; +sb << "\n"; +sb << "// Reinterpret bits as a double (HLSL SM 5.0)\n"; +sb << "__intrinsic_op double asdouble(uint lowbits, uint highbits);\n"; +sb << "\n"; +sb << "// Reinterpret bits as a float (HLSL SM 4.0)\n"; +sb << "__intrinsic_op float asfloat( int x);\n"; +sb << "__intrinsic_op float asfloat(uint x);\n"; +sb << "__generic __intrinsic_op vector asfloat(vector< int,N> x);\n"; +sb << "__generic __intrinsic_op vector asfloat(vector x);\n"; +sb << "__generic __intrinsic_op matrix asfloat(matrix< int,N,M> x);\n"; +sb << "__generic __intrinsic_op matrix asfloat(matrix x);\n"; +sb << "\n"; +sb << "\n"; +sb << "// Inverse sine (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T asin(T x);\n"; +sb << "__generic __intrinsic_op vector asin(vector x);\n"; +sb << "__generic __intrinsic_op matrix asin(matrix x);\n"; +sb << "\n"; +sb << "// Reinterpret bits as an int (HLSL SM 4.0)\n"; +sb << "__intrinsic_op int asint(float x);\n"; +sb << "__intrinsic_op int asint(uint x);\n"; +sb << "__generic __intrinsic_op vector asint(vector x);\n"; +sb << "__generic __intrinsic_op vector asint(vector x);\n"; +sb << "__generic __intrinsic_op matrix asint(matrix x);\n"; +sb << "__generic __intrinsic_op matrix asint(matrix x);\n"; +sb << "\n"; +sb << "// Reinterpret bits of double as a uint (HLSL SM 5.0)\n"; +sb << "__intrinsic_op void asuint(double value, out uint lowbits, out uint highbits);\n"; +sb << "\n"; +sb << "// Reinterpret bits as a uint (HLSL SM 4.0)\n"; +sb << "__intrinsic_op uint asuint(float x);\n"; +sb << "__intrinsic_op uint asuint(int x);\n"; +sb << "__generic __intrinsic_op vector asuint(vector x);\n"; +sb << "__generic __intrinsic_op vector asuint(vector x);\n"; +sb << "__generic __intrinsic_op matrix asuint(matrix x);\n"; +sb << "__generic __intrinsic_op matrix asuint(matrix x);\n"; +sb << "\n"; +sb << "// Inverse tangent (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T atan(T x);\n"; +sb << "__generic __intrinsic_op vector atan(vector x);\n"; +sb << "__generic __intrinsic_op matrix atan(matrix x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl,\"atan($0,$1)\")\n"; +sb << "__intrinsic_op\n"; +sb << "T atan2(T y, T x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl,\"atan($0,$1)\")\n"; +sb << "__intrinsic_op\n"; +sb << "vector atan2(vector y, vector x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl,\"atan($0,$1)\")\n"; +sb << "__intrinsic_op\n"; +sb << "matrix atan2(matrix y, matrix x);\n"; +sb << "\n"; +sb << "// Ceiling (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T ceil(T x);\n"; +sb << "__generic __intrinsic_op vector ceil(vector x);\n"; +sb << "__generic __intrinsic_op matrix ceil(matrix x);\n"; +sb << "\n"; +sb << "\n"; +sb << "// Check access status to tiled resource\n"; +sb << "__intrinsic_op bool CheckAccessFullyMapped(uint status);\n"; +sb << "\n"; +sb << "// Clamp (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T clamp(T x, T min, T max);\n"; +sb << "__generic __intrinsic_op vector clamp(vector x, vector min, vector max);\n"; +sb << "__generic __intrinsic_op matrix clamp(matrix x, matrix min, matrix max);\n"; +sb << "\n"; +sb << "// Clip (discard) fragment conditionally\n"; +sb << "__generic __intrinsic_op void clip(T x);\n"; +sb << "__generic __intrinsic_op void clip(vector x);\n"; +sb << "__generic __intrinsic_op void clip(matrix x);\n"; +sb << "\n"; +sb << "// Cosine\n"; +sb << "__generic __intrinsic_op T cos(T x);\n"; +sb << "__generic __intrinsic_op vector cos(vector x);\n"; +sb << "__generic __intrinsic_op matrix cos(matrix x);\n"; +sb << "\n"; +sb << "// Hyperbolic cosine\n"; +sb << "__generic __intrinsic_op T cosh(T x);\n"; +sb << "__generic __intrinsic_op vector cosh(vector x);\n"; +sb << "__generic __intrinsic_op matrix cosh(matrix x);\n"; +sb << "\n"; +sb << "// Population count\n"; +sb << "__intrinsic_op uint countbits(uint value);\n"; +sb << "\n"; +sb << "// Cross product\n"; +sb << "__generic __intrinsic_op vector cross(vector x, vector y);\n"; +sb << "\n"; +sb << "// Convert encoded color\n"; +sb << "__intrinsic_op int4 D3DCOLORtoUBYTE4(float4 x);\n"; +sb << "\n"; +sb << "// Partial-difference derivatives\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, dFdx)\n"; +sb << "__intrinsic_op\n"; +sb << "T ddx(T x);\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, dFdx)\n"; +sb << "__intrinsic_op\n"; +sb << "vector ddx(vector x);\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, dFdx)\n"; +sb << "__intrinsic_op\n"; +sb << "matrix ddx(matrix x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdxCoarse)\n"; +sb << "__intrinsic_op\n"; +sb << "T ddx_coarse(T x);\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdxCoarse)\n"; +sb << "__intrinsic_op\n"; +sb << "vector ddx_coarse(vector x);\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdxCoarse)\n"; +sb << "__intrinsic_op\n"; +sb << "matrix ddx_coarse(matrix x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdxFine)\n"; +sb << "__intrinsic_op\n"; +sb << "T ddx_fine(T x);\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdxFine)\n"; +sb << "__intrinsic_op\n"; +sb << "vector ddx_fine(vector x);\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdxFine)\n"; +sb << "__intrinsic_op\n"; +sb << "matrix ddx_fine(matrix x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, dFdy)\n"; +sb << "__intrinsic_op\n"; +sb << "T ddy(T x);\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, dFdy)\n"; +sb << "__intrinsic_op\n"; +sb << "vector ddy(vector x);\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, dFdy)\n"; +sb << "__intrinsic_op\n"; +sb << " matrix ddy(matrix x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdyCoarse)\n"; +sb << "__intrinsic_op\n"; +sb << "T ddy_coarse(T x);\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdyCoarse)\n"; +sb << "__intrinsic_op\n"; +sb << "vector ddy_coarse(vector x);\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdyCoarse)\n"; +sb << "__intrinsic_op\n"; +sb << "matrix ddy_coarse(matrix x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdyFine)\n"; +sb << "__intrinsic_op\n"; +sb << "T ddy_fine(T x);\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdyFine)\n"; +sb << "__intrinsic_op\n"; +sb << "vector ddy_fine(vector x);\n"; +sb << "__generic\n"; +sb << "__glsl_extension(GL_ARB_derivative_control)\n"; +sb << "__target_intrinsic(glsl, dFdyFine)\n"; +sb << "__intrinsic_op\n"; +sb << "matrix ddy_fine(matrix x);\n"; +sb << "\n"; +sb << "\n"; +sb << "// Radians to degrees\n"; +sb << "__generic __intrinsic_op T degrees(T x);\n"; +sb << "__generic __intrinsic_op vector degrees(vector x);\n"; +sb << "__generic __intrinsic_op matrix degrees(matrix x);\n"; +sb << "\n"; +sb << "// Matrix determinant\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T determinant(matrix m);\n"; +sb << "\n"; +sb << "// Barrier for device memory\n"; +sb << "__intrinsic_op void DeviceMemoryBarrier();\n"; +sb << "__intrinsic_op void DeviceMemoryBarrierWithGroupSync();\n"; +sb << "\n"; +sb << "// Vector distance\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T distance(vector x, vector y);\n"; +sb << "\n"; +sb << "// Vector dot product\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T dot(vector x, vector y);\n"; +sb << "\n"; +sb << "// Helper for computing distance terms for lighting (obsolete)\n"; +sb << "\n"; +sb << "__generic __intrinsic_op vector dst(vector x, vector y);\n"; +sb << "\n"; +sb << "// Error message\n"; +sb << "\n"; +sb << "// __intrinsic_op void errorf( string format, ... );\n"; +sb << "\n"; +sb << "// Attribute evaluation\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T EvaluateAttributeAtCentroid(T x);\n"; +sb << "__generic __intrinsic_op vector EvaluateAttributeAtCentroid(vector x);\n"; +sb << "__generic __intrinsic_op matrix EvaluateAttributeAtCentroid(matrix x);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T EvaluateAttributeAtSample(T x, uint sampleindex);\n"; +sb << "__generic __intrinsic_op vector EvaluateAttributeAtSample(vector x, uint sampleindex);\n"; +sb << "__generic __intrinsic_op matrix EvaluateAttributeAtSample(matrix x, uint sampleindex);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T EvaluateAttributeSnapped(T x, int2 offset);\n"; +sb << "__generic __intrinsic_op vector EvaluateAttributeSnapped(vector x, int2 offset);\n"; +sb << "__generic __intrinsic_op matrix EvaluateAttributeSnapped(matrix x, int2 offset);\n"; +sb << "\n"; +sb << "// Base-e exponent\n"; +sb << "__generic __intrinsic_op T exp(T x);\n"; +sb << "__generic __intrinsic_op vector exp(vector x);\n"; +sb << "__generic __intrinsic_op matrix exp(matrix x);\n"; +sb << "\n"; +sb << "// Base-2 exponent\n"; +sb << "__generic __intrinsic_op T exp2(T x);\n"; +sb << "__generic __intrinsic_op vector exp2(vector x);\n"; +sb << "__generic __intrinsic_op matrix exp2(matrix x);\n"; +sb << "\n"; +sb << "// Convert 16-bit float stored in low bits of integer\n"; +sb << "__intrinsic_op float f16tof32(uint value);\n"; +sb << "__generic __intrinsic_op vector f16tof32(vector value);\n"; +sb << "\n"; +sb << "// Convert to 16-bit float stored in low bits of integer\n"; +sb << "__intrinsic_op uint f32tof16(float value);\n"; +sb << "__generic __intrinsic_op vector f32tof16(vector value);\n"; +sb << "\n"; +sb << "// Flip surface normal to face forward, if needed\n"; +sb << "__generic __intrinsic_op vector faceforward(vector n, vector i, vector ng);\n"; +sb << "\n"; +sb << "// Find first set bit starting at high bit and working down\n"; +sb << "__intrinsic_op int firstbithigh(int value);\n"; +sb << "__generic __intrinsic_op vector firstbithigh(vector value);\n"; +sb << "\n"; +sb << "__intrinsic_op uint firstbithigh(uint value);\n"; +sb << "__generic __intrinsic_op vector firstbithigh(vector value);\n"; +sb << "\n"; +sb << "// Find first set bit starting at low bit and working up\n"; +sb << "__intrinsic_op int firstbitlow(int value);\n"; +sb << "__generic __intrinsic_op vector firstbitlow(vector value);\n"; +sb << "\n"; +sb << "__intrinsic_op uint firstbitlow(uint value);\n"; +sb << "__generic __intrinsic_op vector firstbitlow(vector value);\n"; +sb << "\n"; +sb << "// Floor (HLSL SM 1.0)\n"; +sb << "__generic __intrinsic_op T floor(T x);\n"; +sb << "__generic __intrinsic_op vector floor(vector x);\n"; +sb << "__generic __intrinsic_op matrix floor(matrix x);\n"; +sb << "\n"; +sb << "// Fused multiply-add for doubles\n"; +sb << "__intrinsic_op double fma(double a, double b, double c);\n"; +sb << "__generic __intrinsic_op vector fma(vector a, vector b, vector c);\n"; +sb << "__generic __intrinsic_op matrix fma(matrix a, matrix b, matrix c);\n"; +sb << "\n"; +sb << "// Floating point remainder of x/y\n"; +sb << "__generic __intrinsic_op T fmod(T x, T y);\n"; +sb << "__generic __intrinsic_op vector fmod(vector x, vector y);\n"; +sb << "__generic __intrinsic_op matrix fmod(matrix x, matrix y);\n"; +sb << "\n"; +sb << "// Fractional part\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, fract)\n"; +sb << "__intrinsic_op\n"; +sb << "T frac(T x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, fract)\n"; +sb << "__intrinsic_op\n"; +sb << "vector frac(vector x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, fract)\n"; +sb << "__intrinsic_op\n"; +sb << "matrix frac(matrix x);\n"; +sb << "\n"; +sb << "// Split float into mantissa and exponent\n"; +sb << "__generic __intrinsic_op T frexp(T x, out T exp);\n"; +sb << "__generic __intrinsic_op vector frexp(vector x, out vector exp);\n"; +sb << "__generic __intrinsic_op matrix frexp(matrix x, out matrix exp);\n"; +sb << "\n"; +sb << "// Texture filter width\n"; +sb << "__generic __intrinsic_op T fwidth(T x);\n"; +sb << "__generic __intrinsic_op vector fwidth(vector x);\n"; +sb << "__generic __intrinsic_op matrix fwidth(matrix x);\n"; +sb << "\n"; +sb << "// Get number of samples in render target\n"; +sb << "__intrinsic_op uint GetRenderTargetSampleCount();\n"; +sb << "\n"; +sb << "// Get position of given sample\n"; +sb << "__intrinsic_op float2 GetRenderTargetSamplePosition(int Index);\n"; +sb << "\n"; +sb << "// Group memory barrier\n"; +sb << "__intrinsic_op void GroupMemoryBarrier();\n"; +sb << "__intrinsic_op void GroupMemoryBarrierWithGroupSync();\n"; +sb << "\n"; +sb << "// Atomics\n"; +sb << "__intrinsic_op void InterlockedAdd(in out int dest, int value, out int original_value);\n"; +sb << "__intrinsic_op void InterlockedAdd(in out uint dest, uint value, out uint original_value);\n"; +sb << "\n"; +sb << "__intrinsic_op void InterlockedAnd(in out int dest, int value, out int original_value);\n"; +sb << "__intrinsic_op void InterlockedAnd(in out uint dest, uint value, out uint original_value);\n"; +sb << "\n"; +sb << "__intrinsic_op void InterlockedCompareExchange(in out int dest, int compare_value, int value, out int original_value);\n"; +sb << "__intrinsic_op void InterlockedCompareExchange(in out uint dest, uint compare_value, uint value, out uint original_value);\n"; +sb << "\n"; +sb << "__intrinsic_op void InterlockedCompareStore(in out int dest, int compare_value, int value);\n"; +sb << "__intrinsic_op void InterlockedCompareStore(in out uint dest, uint compare_value, uint value);\n"; +sb << "\n"; +sb << "__intrinsic_op void InterlockedExchange(in out int dest, int value, out int original_value);\n"; +sb << "__intrinsic_op void InterlockedExchange(in out uint dest, uint value, out uint original_value);\n"; +sb << "\n"; +sb << "__intrinsic_op void InterlockedMax(in out int dest, int value, out int original_value);\n"; +sb << "__intrinsic_op void InterlockedMax(in out uint dest, uint value, out uint original_value);\n"; +sb << "\n"; +sb << "__intrinsic_op void InterlockedMin(in out int dest, int value, out int original_value);\n"; +sb << "__intrinsic_op void InterlockedMin(in out uint dest, uint value, out uint original_value);\n"; +sb << "\n"; +sb << "__intrinsic_op void InterlockedOr(in out int dest, int value, out int original_value);\n"; +sb << "__intrinsic_op void InterlockedOr(in out uint dest, uint value, out uint original_value);\n"; +sb << "\n"; +sb << "__intrinsic_op void InterlockedXor(in out int dest, int value, out int original_value);\n"; +sb << "__intrinsic_op void InterlockedXor(in out uint dest, uint value, out uint original_value);\n"; +sb << "\n"; +sb << "// Is floating-point value finite?\n"; +sb << "__generic __intrinsic_op bool isfinite(T x);\n"; +sb << "__generic __intrinsic_op vector isfinite(vector x);\n"; +sb << "__generic __intrinsic_op matrix isfinite(matrix x);\n"; +sb << "\n"; +sb << "// Is floating-point value infinite?\n"; +sb << "__generic __intrinsic_op bool isinf(T x);\n"; +sb << "__generic __intrinsic_op vector isinf(vector x);\n"; +sb << "__generic __intrinsic_op matrix isinf(matrix x);\n"; +sb << "\n"; +sb << "// Is floating-point value not-a-number?\n"; +sb << "__generic __intrinsic_op bool isnan(T x);\n"; +sb << "__generic __intrinsic_op vector isnan(vector x);\n"; +sb << "__generic __intrinsic_op matrix isnan(matrix x);\n"; +sb << "\n"; +sb << "// Construct float from mantissa and exponent\n"; +sb << "__generic __intrinsic_op T ldexp(T x, T exp);\n"; +sb << "__generic __intrinsic_op vector ldexp(vector x, vector exp);\n"; +sb << "__generic __intrinsic_op matrix ldexp(matrix x, matrix exp);\n"; +sb << "\n"; +sb << "// Vector length\n"; +sb << "__generic __intrinsic_op T length(vector x);\n"; +sb << "\n"; +sb << "// Linear interpolation\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, mix)\n"; +sb << "__intrinsic_op\n"; +sb << "T lerp(T x, T y, T s);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, mix)\n"; +sb << "__intrinsic_op\n"; +sb << "vector lerp(vector x, vector y, vector s);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, mix)\n"; +sb << "__intrinsic_op\n"; +sb << "matrix lerp(matrix x, matrix y, matrix s);\n"; +sb << "\n"; +sb << "// Legacy lighting function (obsolete)\n"; +sb << "__intrinsic_op float4 lit(float n_dot_l, float n_dot_h, float m);\n"; +sb << "\n"; +sb << "// Base-e logarithm\n"; +sb << "__generic __intrinsic_op T log(T x);\n"; +sb << "__generic __intrinsic_op vector log(vector x);\n"; +sb << "__generic __intrinsic_op matrix log(matrix x);\n"; +sb << "\n"; +sb << "// Base-10 logarithm\n"; +sb << "__generic __intrinsic_op T log10(T x);\n"; +sb << "__generic __intrinsic_op vector log10(vector x);\n"; +sb << "__generic __intrinsic_op matrix log10(matrix x);\n"; +sb << "\n"; +sb << "// Base-2 logarithm\n"; +sb << "__generic __intrinsic_op T log2(T x);\n"; +sb << "__generic __intrinsic_op vector log2(vector x);\n"; +sb << "__generic __intrinsic_op matrix log2(matrix x);\n"; +sb << "\n"; +sb << "// multiply-add\n"; +sb << "__generic __intrinsic_op T mad(T mvalue, T avalue, T bvalue);\n"; +sb << "__generic __intrinsic_op vector mad(vector mvalue, vector avalue, vector bvalue);\n"; +sb << "__generic __intrinsic_op matrix mad(matrix mvalue, matrix avalue, matrix bvalue);\n"; +sb << "\n"; +sb << "// maximum\n"; +sb << "__generic __intrinsic_op T max(T x, T y);\n"; +sb << "__generic __intrinsic_op vector max(vector x, vector y);\n"; +sb << "__generic __intrinsic_op matrix max(matrix x, matrix y);\n"; +sb << "\n"; +sb << "// minimum\n"; +sb << "__generic __intrinsic_op T min(T x, T y);\n"; +sb << "__generic __intrinsic_op vector min(vector x, vector y);\n"; +sb << "__generic __intrinsic_op matrix min(matrix x, matrix y);\n"; +sb << "\n"; +sb << "// split into integer and fractional parts (both with same sign)\n"; +sb << "__generic __intrinsic_op T modf(T x, out T ip);\n"; +sb << "__generic __intrinsic_op vector modf(vector x, out vector ip);\n"; +sb << "__generic __intrinsic_op matrix modf(matrix x, out matrix ip);\n"; +sb << "\n"; +sb << "// msad4 (whatever that is)\n"; +sb << "__intrinsic_op uint4 msad4(uint reference, uint2 source, uint4 accum);\n"; +sb << "\n"; +sb << "// General inner products\n"; +sb << "\n"; +sb << "// scalar-scalar\n"; +sb << "__generic __intrinsic_op T mul(T x, T y);\n"; +sb << "\n"; +sb << "// scalar-vector and vector-scalar\n"; +sb << "__generic __intrinsic_op vector mul(vector x, T y);\n"; +sb << "__generic __intrinsic_op vector mul(T x, vector y);\n"; +sb << "\n"; +sb << "// scalar-matrix and matrix-scalar\n"; +sb << "__generic __intrinsic_op matrix mul(matrix x, T y);\n"; +sb << "__generic __intrinsic_op matrix mul(T x, matrix y);\n"; +sb << "\n"; +sb << "// vector-vector (dot product)\n"; +sb << "__generic __intrinsic_op(dot) T mul(vector x, vector y);\n"; +sb << "\n"; +sb << "// vector-matrix\n"; +sb << "__generic __intrinsic_op(mulVectorMatrix) vector mul(vector x, matrix y);\n"; +sb << "\n"; +sb << "// matrix-vector\n"; +sb << "__generic __intrinsic_op(mulMatrixVector) vector mul(matrix x, vector y);\n"; +sb << "\n"; +sb << "// matrix-matrix\n"; +sb << "__generic __intrinsic_op(mulMatrixMatrix) matrix mul(matrix x, matrix y);\n"; +sb << "\n"; +sb << "// noise (deprecated)\n"; +sb << "__intrinsic_op float noise(float x);\n"; +sb << "__generic __intrinsic_op float noise(vector x);\n"; +sb << "\n"; +sb << "// Normalize a vector\n"; +sb << "__generic __intrinsic_op vector normalize(vector x);\n"; +sb << "\n"; +sb << "// Raise to a power\n"; +sb << "__generic __intrinsic_op T pow(T x, T y);\n"; +sb << "__generic __intrinsic_op vector pow(vector x, vector y);\n"; +sb << "__generic __intrinsic_op matrix pow(matrix x, matrix y);\n"; +sb << "\n"; +sb << "// Output message\n"; +sb << "\n"; +sb << "// __intrinsic_op void printf( string format, ... );\n"; +sb << "\n"; +sb << "// Tessellation factor fixup routines\n"; +sb << "\n"; +sb << "__intrinsic_op void Process2DQuadTessFactorsAvg(\n"; +sb << " in float4 RawEdgeFactors,\n"; +sb << " in float2 InsideScale,\n"; +sb << " out float4 RoundedEdgeTessFactors,\n"; +sb << " out float2 RoundedInsideTessFactors,\n"; +sb << " out float2 UnroundedInsideTessFactors);\n"; +sb << "\n"; +sb << "__intrinsic_op void Process2DQuadTessFactorsMax(\n"; +sb << " in float4 RawEdgeFactors,\n"; +sb << " in float2 InsideScale,\n"; +sb << " out float4 RoundedEdgeTessFactors,\n"; +sb << " out float2 RoundedInsideTessFactors,\n"; +sb << " out float2 UnroundedInsideTessFactors);\n"; +sb << "\n"; +sb << "__intrinsic_op void Process2DQuadTessFactorsMin(\n"; +sb << " in float4 RawEdgeFactors,\n"; +sb << " in float2 InsideScale,\n"; +sb << " out float4 RoundedEdgeTessFactors,\n"; +sb << " out float2 RoundedInsideTessFactors,\n"; +sb << " out float2 UnroundedInsideTessFactors);\n"; +sb << "\n"; +sb << "__intrinsic_op void ProcessIsolineTessFactors(\n"; +sb << " in float RawDetailFactor,\n"; +sb << " in float RawDensityFactor,\n"; +sb << " out float RoundedDetailFactor,\n"; +sb << " out float RoundedDensityFactor);\n"; +sb << "\n"; +sb << "__intrinsic_op void ProcessQuadTessFactorsAvg(\n"; +sb << " in float4 RawEdgeFactors,\n"; +sb << " in float InsideScale,\n"; +sb << " out float4 RoundedEdgeTessFactors,\n"; +sb << " out float2 RoundedInsideTessFactors,\n"; +sb << " out float2 UnroundedInsideTessFactors);\n"; +sb << "\n"; +sb << "__intrinsic_op void ProcessQuadTessFactorsMax(\n"; +sb << " in float4 RawEdgeFactors,\n"; +sb << " in float InsideScale,\n"; +sb << " out float4 RoundedEdgeTessFactors,\n"; +sb << " out float2 RoundedInsideTessFactors,\n"; +sb << " out float2 UnroundedInsideTessFactors);\n"; +sb << "\n"; +sb << "__intrinsic_op void ProcessQuadTessFactorsMin(\n"; +sb << " in float4 RawEdgeFactors,\n"; +sb << " in float InsideScale,\n"; +sb << " out float4 RoundedEdgeTessFactors,\n"; +sb << " out float2 RoundedInsideTessFactors,\n"; +sb << " out float2 UnroundedInsideTessFactors);\n"; +sb << "\n"; +sb << "__intrinsic_op void ProcessTriTessFactorsAvg(\n"; +sb << " in float3 RawEdgeFactors,\n"; +sb << " in float InsideScale,\n"; +sb << " out float3 RoundedEdgeTessFactors,\n"; +sb << " out float RoundedInsideTessFactor,\n"; +sb << " out float UnroundedInsideTessFactor);\n"; +sb << "\n"; +sb << "__intrinsic_op void ProcessTriTessFactorsMax(\n"; +sb << " in float3 RawEdgeFactors,\n"; +sb << " in float InsideScale,\n"; +sb << " out float3 RoundedEdgeTessFactors,\n"; +sb << " out float RoundedInsideTessFactor,\n"; +sb << " out float UnroundedInsideTessFactor);\n"; +sb << "\n"; +sb << "__intrinsic_op void ProcessTriTessFactorsMin(\n"; +sb << " in float3 RawEdgeFactors,\n"; +sb << " in float InsideScale,\n"; +sb << " out float3 RoundedEdgeTessFactors,\n"; +sb << " out float RoundedInsideTessFactors,\n"; +sb << " out float UnroundedInsideTessFactors);\n"; +sb << "\n"; +sb << "// Degrees to radians\n"; +sb << "__generic __intrinsic_op T radians(T x);\n"; +sb << "__generic __intrinsic_op vector radians(vector x);\n"; +sb << "__generic __intrinsic_op matrix radians(matrix x);\n"; +sb << "\n"; +sb << "// Approximate reciprocal\n"; +sb << "__generic __intrinsic_op T rcp(T x);\n"; +sb << "__generic __intrinsic_op vector rcp(vector x);\n"; +sb << "__generic __intrinsic_op matrix rcp(matrix x);\n"; +sb << "\n"; +sb << "// Reflect incident vector across plane with given normal\n"; +sb << "__generic\n"; +sb << "__intrinsic_op\n"; +sb << "vector reflect(vector i, vector n);\n"; +sb << "\n"; +sb << "// Refract incident vector given surface normal and index of refraction\n"; +sb << "__generic\n"; +sb << "__intrinsic_op\n"; +sb << "vector refract(vector i, vector n, float eta);\n"; +sb << "\n"; +sb << "// Reverse order of bits\n"; +sb << "__intrinsic_op uint reversebits(uint value);\n"; +sb << "__generic vector reversebits(vector value);\n"; +sb << "\n"; +sb << "// Round-to-nearest\n"; +sb << "__generic __intrinsic_op T round(T x);\n"; +sb << "__generic __intrinsic_op vector round(vector x);\n"; +sb << "__generic __intrinsic_op matrix round(matrix x);\n"; +sb << "\n"; +sb << "// Reciprocal of square root\n"; +sb << "__generic __intrinsic_op T rsqrt(T x);\n"; +sb << "__generic __intrinsic_op vector rsqrt(vector x);\n"; +sb << "__generic __intrinsic_op matrix rsqrt(matrix x);\n"; +sb << "\n"; +sb << "// Clamp value to [0,1] range\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, \"clamp($0, 0, 1)\") __intrinsic_op\n"; +sb << "T saturate(T x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, \"clamp($0, 0, 1)\") __intrinsic_op\n"; +sb << "vector saturate(vector x);\n"; +sb << "\n"; +sb << "__generic\n"; +sb << "__target_intrinsic(glsl, \"clamp($0, 0, 1)\") __intrinsic_op\n"; +sb << "matrix saturate(matrix x);\n"; +sb << "\n"; +sb << "\n"; +sb << "// Extract sign of value\n"; +sb << "__generic __intrinsic_op int sign(T x);\n"; +sb << "__generic __intrinsic_op vector sign(vector x);\n"; +sb << "__generic __intrinsic_op matrix sign(matrix x);\n"; +sb << "\n"; +sb << "\n"; +sb << "// Sine\n"; +sb << "__generic __intrinsic_op T sin(T x);\n"; +sb << "__generic __intrinsic_op vector sin(vector x);\n"; +sb << "__generic __intrinsic_op matrix sin(matrix x);\n"; +sb << "\n"; +sb << "// Sine and cosine\n"; +sb << "__generic __intrinsic_op void sincos(T x, out T s, out T c);\n"; +sb << "__generic __intrinsic_op void sincos(vector x, out vector s, out vector c);\n"; +sb << "__generic __intrinsic_op void sincos(matrix x, out matrix s, out matrix c);\n"; +sb << "\n"; +sb << "// Hyperbolic Sine\n"; +sb << "__generic __intrinsic_op T sinh(T x);\n"; +sb << "__generic __intrinsic_op vector sinh(vector x);\n"; +sb << "__generic __intrinsic_op matrix sinh(matrix x);\n"; +sb << "\n"; +sb << "// Smooth step (Hermite interpolation)\n"; +sb << "__generic __intrinsic_op T smoothstep(T min, T max, T x);\n"; +sb << "__generic __intrinsic_op vector smoothstep(vector min, vector max, vector x);\n"; +sb << "__generic __intrinsic_op matrix smoothstep(matrix min, matrix max, matrix x);\n"; +sb << "\n"; +sb << "// Square root\n"; +sb << "__generic __intrinsic_op T sqrt(T x);\n"; +sb << "__generic __intrinsic_op vector sqrt(vector x);\n"; +sb << "__generic __intrinsic_op matrix sqrt(matrix x);\n"; +sb << "\n"; +sb << "// Step function\n"; +sb << "__generic __intrinsic_op T step(T y, T x);\n"; +sb << "__generic __intrinsic_op vector step(vector y, vector x);\n"; +sb << "__generic __intrinsic_op matrix step(matrix y, matrix x);\n"; +sb << "\n"; +sb << "// Tangent\n"; +sb << "__generic __intrinsic_op T tan(T x);\n"; +sb << "__generic __intrinsic_op vector tan(vector x);\n"; +sb << "__generic __intrinsic_op matrix tan(matrix x);\n"; +sb << "\n"; +sb << "// Hyperbolic tangent\n"; +sb << "__generic __intrinsic_op T tanh(T x);\n"; +sb << "__generic __intrinsic_op vector tanh(vector x);\n"; +sb << "__generic __intrinsic_op matrix tanh(matrix x);\n"; +sb << "\n"; +sb << "// Legacy texture-fetch operations\n"; +sb << "\n"; +sb << "/*\n"; +sb << "__intrinsic_op float4 tex1D(sampler1D s, float t);\n"; +sb << "__intrinsic_op float4 tex1D(sampler1D s, float t, float ddx, float ddy);\n"; +sb << "__intrinsic_op float4 tex1Dbias(sampler1D s, float4 t);\n"; +sb << "__intrinsic_op float4 tex1Dgrad(sampler1D s, float t, float ddx, float ddy);\n"; +sb << "__intrinsic_op float4 tex1Dlod(sampler1D s, float4 t);\n"; +sb << "__intrinsic_op float4 tex1Dproj(sampler1D s, float4 t);\n"; +sb << "\n"; +sb << "__intrinsic_op float4 tex2D(sampler2D s, float2 t);\n"; +sb << "__intrinsic_op float4 tex2D(sampler2D s, float2 t, float2 ddx, float2 ddy);\n"; +sb << "__intrinsic_op float4 tex2Dbias(sampler2D s, float4 t);\n"; +sb << "__intrinsic_op float4 tex2Dgrad(sampler2D s, float2 t, float2 ddx, float2 ddy);\n"; +sb << "__intrinsic_op float4 tex2Dlod(sampler2D s, float4 t);\n"; +sb << "__intrinsic_op float4 tex2Dproj(sampler2D s, float4 t);\n"; +sb << "\n"; +sb << "__intrinsic_op float4 tex3D(sampler3D s, float3 t);\n"; +sb << "__intrinsic_op float4 tex3D(sampler3D s, float3 t, float3 ddx, float3 ddy);\n"; +sb << "__intrinsic_op float4 tex3Dbias(sampler3D s, float4 t);\n"; +sb << "__intrinsic_op float4 tex3Dgrad(sampler3D s, float3 t, float3 ddx, float3 ddy);\n"; +sb << "__intrinsic_op float4 tex3Dlod(sampler3D s, float4 t);\n"; +sb << "__intrinsic_op float4 tex3Dproj(sampler3D s, float4 t);\n"; +sb << "\n"; +sb << "__intrinsic_op float4 texCUBE(samplerCUBE s, float3 t);\n"; +sb << "__intrinsic_op float4 texCUBE(samplerCUBE s, float3 t, float3 ddx, float3 ddy);\n"; +sb << "__intrinsic_op float4 texCUBEbias(samplerCUBE s, float4 t);\n"; +sb << "__intrinsic_op float4 texCUBEgrad(samplerCUBE s, float3 t, float3 ddx, float3 ddy);\n"; +sb << "__intrinsic_op float4 texCUBElod(samplerCUBE s, float4 t);\n"; +sb << "__intrinsic_op float4 texCUBEproj(samplerCUBE s, float4 t);\n"; +sb << "*/\n"; +sb << "\n"; +sb << "// Matrix transpose\n"; +sb << "__generic __intrinsic_op matrix transpose(matrix x);\n"; +sb << "\n"; +sb << "// Truncate to integer\n"; +sb << "__generic __intrinsic_op T trunc(T x);\n"; +sb << "__generic __intrinsic_op vector trunc(vector x);\n"; +sb << "__generic __intrinsic_op matrix trunc(matrix x);\n"; +sb << "\n"; +sb << "// Shader model 6.0 stuff\n"; +sb << "\n"; +sb << "__intrinsic_op uint GlobalOrderedCountIncrement(uint countToAppendForThisLane);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T QuadReadLaneAt(T sourceValue, int quadLaneID);\n"; +sb << "__generic __intrinsic_op vector QuadReadLaneAt(vector sourceValue, int quadLaneID);\n"; +sb << "__generic __intrinsic_op matrix QuadReadLaneAt(matrix sourceValue, int quadLaneID);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T QuadSwapX(T localValue);\n"; +sb << "__generic __intrinsic_op vector QuadSwapX(vector localValue);\n"; +sb << "__generic __intrinsic_op matrix QuadSwapX(matrix localValue);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T QuadSwapY(T localValue);\n"; +sb << "__generic __intrinsic_op vector QuadSwapY(vector localValue);\n"; +sb << "__generic __intrinsic_op matrix QuadSwapY(matrix localValue);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveAllBitAnd(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveAllBitAnd(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveAllBitAnd(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveAllBitOr(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveAllBitOr(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveAllBitOr(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveAllBitXor(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveAllBitXor(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveAllBitXor(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveAllMax(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveAllMax(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveAllMax(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveAllMin(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveAllMin(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveAllMin(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveAllProduct(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveAllProduct(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveAllProduct(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveAllSum(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveAllSum(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveAllSum(matrix expr);\n"; +sb << "\n"; +sb << "__intrinsic_op bool WaveAllEqual(bool expr);\n"; +sb << "__intrinsic_op bool WaveAllTrue(bool expr);\n"; +sb << "__intrinsic_op bool WaveAnyTrue(bool expr);\n"; +sb << "\n"; +sb << "uint64_t WaveBallot(bool expr);\n"; +sb << "\n"; +sb << "uint WaveGetLaneCount();\n"; +sb << "uint WaveGetLaneIndex();\n"; +sb << "uint WaveGetOrderedIndex();\n"; +sb << "\n"; +sb << "bool WaveIsHelperLane();\n"; +sb << "\n"; +sb << "bool WaveOnce();\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WavePrefixProduct(T expr);\n"; +sb << "__generic __intrinsic_op vector WavePrefixProduct(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WavePrefixProduct(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WavePrefixSum(T expr);\n"; +sb << "__generic __intrinsic_op vector WavePrefixSum(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WavePrefixSum(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveReadFirstLane(T expr);\n"; +sb << "__generic __intrinsic_op vector WaveReadFirstLane(vector expr);\n"; +sb << "__generic __intrinsic_op matrix WaveReadFirstLane(matrix expr);\n"; +sb << "\n"; +sb << "__generic __intrinsic_op T WaveReadLaneAt(T expr, int laneIndex);\n"; +sb << "__generic __intrinsic_op vector WaveReadLaneAt(vector expr, int laneIndex);\n"; +sb << "__generic __intrinsic_op matrix WaveReadLaneAt(matrix expr, int laneIndex);\n"; +sb << "\n"; +sb << "// `typedef`s to help with the fact that HLSL has been sorta-kinda case insensitive at various points\n"; +sb << "typedef Texture2D texture2D;\n"; +sb << "\n"; +sb << ""; + + +// Component-wise multiplication ops +for(auto op : binaryOps) +{ + switch (op.opCode) + { + default: + continue; + + case kIROp_Mul: + case kIRPseudoOp_MulAssign: + break; + } + + for (auto type : kBaseTypes) + { + if ((type.flags & op.flags) == 0) + continue; + + char const* leftType = type.name; + char const* rightType = leftType; + char const* resultType = leftType; + + char const* leftQual = ""; + if(op.flags & ASSIGNMENT) leftQual = "in out "; + + sb << "__generic "; + sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n"; + } +} + +// + +// Buffer types + +static const struct { + char const* name; + SlangResourceAccess access; +} kBaseBufferAccessLevels[] = { + { "", SLANG_RESOURCE_ACCESS_READ }, + { "RW", SLANG_RESOURCE_ACCESS_READ_WRITE }, + { "RasterizerOrdered", SLANG_RESOURCE_ACCESS_RASTER_ORDERED }, +}; +static const int kBaseBufferAccessLevelCount = sizeof(kBaseBufferAccessLevels) / sizeof(kBaseBufferAccessLevels[0]); + +for (int aa = 0; aa < kBaseBufferAccessLevelCount; ++aa) +{ + + sb << "__generic __magic_type(Texture, "; + sb << ResourceType::makeFlavor(ResourceType::Shape::ShapeBuffer, kBaseBufferAccessLevels[aa].access); + sb << ") struct "; + sb << kBaseBufferAccessLevels[aa].name; + sb << "Buffer {\n"; + + sb << "__intrinsic_op void GetDimensions(out uint dim);\n"; + + sb << "__target_intrinsic(glsl, \"texelFetch($P, $0)$z\")\n"; + sb << "__intrinsic_op T Load(int location);\n"; + + sb << "__intrinsic_op T Load(int location, out uint status);\n"; + + sb << "__target_intrinsic(glsl, \"texelFetch($P, int($0))$z\")\n"; + sb << "__intrinsic_op __subscript(uint index) -> T"; + + if (kBaseBufferAccessLevels[aa].access != SLANG_RESOURCE_ACCESS_READ) + { + sb << " { get; set; }\n"; + } + else + { + sb << ";\n"; + } + + sb << "};\n"; +} + +sb << ""; diff --git a/source/slang/ir.h b/source/slang/ir.h index a557e22f5..9c3124478 100644 --- a/source/slang/ir.h +++ b/source/slang/ir.h @@ -226,7 +226,7 @@ struct IRInst // All existing uses of `IRValue` should move to `IRInst` typedef IRInst IRValue; -typedef long long IRIntegerValue; +typedef int64_t IRIntegerValue; typedef double IRFloatingPointValue; struct IRConstant : IRInst diff --git a/source/slang/lexer.h b/source/slang/lexer.h index 9ea793d73..23eddf04e 100644 --- a/source/slang/lexer.h +++ b/source/slang/lexer.h @@ -114,7 +114,7 @@ namespace Slang String getStringLiteralTokenValue(Token const& token); String getFileNameTokenValue(Token const& token); - typedef long long IntegerLiteralValue; + typedef int64_t IntegerLiteralValue; typedef double FloatingPointLiteralValue; IntegerLiteralValue getIntegerLiteralValue(Token const& token, String* outSuffix = 0); diff --git a/source/slang/lookup.h b/source/slang/lookup.h index b8223caa6..be7cb30bc 100644 --- a/source/slang/lookup.h +++ b/source/slang/lookup.h @@ -1,7 +1,7 @@ #ifndef SLANG_LOOKUP_H_INCLUDED #define SLANG_LOOKUP_H_INCLUDED -#include "Syntax.h" +#include "syntax.h" namespace Slang { diff --git a/source/slang/lower-to-ir.cpp b/source/slang/lower-to-ir.cpp index 464d5d50a..06ad66bc4 100644 --- a/source/slang/lower-to-ir.cpp +++ b/source/slang/lower-to-ir.cpp @@ -836,7 +836,7 @@ struct ValLoweringVisitor : ValVisitorgetBaseType(type->BaseType); + return getBuilder()->getBaseType(type->baseType); } LoweredTypeInfo visitVectorExpressionType(VectorExpressionType* type) @@ -876,7 +876,7 @@ struct ValLoweringVisitor : ValVisitorBaseType); + auto loweredElementType = lowerType(context, type->baseType); if (auto elementCount = type->ArrayLength) { auto irElementCount = lowerSimpleVal(context, elementCount); @@ -984,7 +984,7 @@ struct ExprLoweringVisitorBase : ExprVisitor // as the visitor itself. LoweredValInfo lowerSubExpr(Expr* expr) { - return dispatch(expr); + return this->dispatch(expr); } @@ -2306,7 +2306,8 @@ struct DeclLoweringVisitor : DeclVisitor template DeclRef createDefaultSpecializedDeclRef(D* decl) { - return createDefaultSpecializedDeclRefImpl(decl).As(); + DeclRef declRef = createDefaultSpecializedDeclRefImpl(decl); + return declRef.As(); } diff --git a/source/slang/lower.cpp b/source/slang/lower.cpp index 391221f47..85f19f14c 100644 --- a/source/slang/lower.cpp +++ b/source/slang/lower.cpp @@ -36,6 +36,103 @@ struct CloneVisitor // +// + +class TupleExpr; +class TupleVarDecl; +class VaryingTupleExpr; +class VaryingTupleVarDecl; + + +// The result of lowering a declaration will usually be a declaration, +// but it might also be a "tuple" declaration, in cases where we needed +// to sclarize (or partially scalarize) things to guarantee validity. +struct LoweredDecl +{ + enum class Flavor + { + Decl, // A single declaration (the default case) + Tuple, // A `TupleVarDecl` representing multiple decls + VaryingTuple, // A `VaryingTupleVarDecl` representing multiple decls + }; + + LoweredDecl() + : flavor(Flavor::Decl) + {} + + LoweredDecl(Decl* decl) + : value(decl) + , flavor(Flavor::Decl) + {} + + LoweredDecl(TupleVarDecl* decl) + : value((RefObject*) decl) + , flavor(Flavor::Tuple) + {} + + LoweredDecl(VaryingTupleVarDecl* decl) + : value((RefObject*) decl) + , flavor(Flavor::VaryingTuple) + {} + + Flavor getFlavor() const { return flavor; } + RefObject* getValue() const { return value; } + + Decl* getDecl() const + { + SLANG_ASSERT(getFlavor() == Flavor::Decl); + return (Decl*) value.Ptr(); + } + + TupleVarDecl* getTupleDecl() const + { + SLANG_ASSERT(getFlavor() == Flavor::Tuple); + return (TupleVarDecl*) value.Ptr(); + } + + VaryingTupleVarDecl* getVaryingTupleDecl() const + { + SLANG_ASSERT(getFlavor() == Flavor::VaryingTuple); + return (VaryingTupleVarDecl*) value.Ptr(); + } + + Decl* asDecl() const + { + return (getFlavor() == Flavor::Decl) ? getDecl() : nullptr; + } + + TupleVarDecl* asTupleDecl() const + { + return (getFlavor() == Flavor::Tuple) ? getTupleDecl() : nullptr; + } + + VaryingTupleVarDecl* asVaryingTupleDecl() const + { + return (getFlavor() == Flavor::VaryingTuple) ? getVaryingTupleDecl() : nullptr; + } + +private: + RefPtr value; + Flavor flavor; +}; + +struct LoweredDeclRef +{ +public: + LoweredDecl decl; + RefPtr substitutions; + + LoweredDecl getDecl() { return decl; } + + template + DeclRef As() + { + return DeclRef(decl.getDecl(), substitutions).As(); + } +}; + +// + template struct StructuralTransformVisitorBase { @@ -54,7 +151,8 @@ struct StructuralTransformVisitorBase template DeclRef transformDeclField(DeclRef const& decl) { - return visitor->translateDeclRef(decl).As(); + LoweredDeclRef declRef = visitor->translateDeclRef(decl); + return declRef.As(); } TypeExp transformSyntaxField(TypeExp const& typeExp) @@ -89,7 +187,8 @@ struct StructuralTransformVisitorBase RefPtr transformSyntaxField(ScopeDecl* decl) { if(!decl) return nullptr; - return visitor->transformSyntaxField(decl).As(); + RefPtr transformed = visitor->transformSyntaxField(decl); + return transformed.As(); } template @@ -104,6 +203,7 @@ struct StructuralTransformVisitorBase } }; +#if 0 template RefPtr structuralTransform( Stmt* stmt, @@ -113,6 +213,7 @@ RefPtr structuralTransform( transformer.visitor = visitor; return transformer.dispatch(stmt); } +#endif template struct StructuralTransformExprVisitor @@ -121,21 +222,26 @@ struct StructuralTransformExprVisitor { void transformFields(Expr* result, Expr* obj) { - result->type = transformSyntaxField(obj->type); + result->type = this->transformSyntaxField(obj->type); } +#define ABSTRACT_SYNTAX_CLASS(NAME, BASE, ...) \ + void transformFields(NAME* result, NAME* obj) { \ + this->transformFields((BASE*) result, (BASE*) obj); \ + /* end */ + #define SYNTAX_CLASS(NAME, BASE, ...) \ - RefPtr visit##NAME(NAME* obj) { \ + RefPtr visit##NAME(NAME* obj) { \ RefPtr result = new NAME(*obj); \ transformFields(result, obj); \ return result; \ } \ - void transformFields(NAME* result, NAME* obj) { \ - transformFields((BASE*) result, (BASE*) obj); \ + ABSTRACT_SYNTAX_CLASS(NAME, BASE) \ + /* end */ -#define SYNTAX_FIELD(TYPE, NAME) result->NAME = transformSyntaxField(obj->NAME); -#define DECL_FIELD(TYPE, NAME) result->NAME = transformDeclField(obj->NAME); +#define SYNTAX_FIELD(TYPE, NAME) result->NAME = this->transformSyntaxField(obj->NAME); +#define DECL_FIELD(TYPE, NAME) result->NAME = this->transformDeclField(obj->NAME); #define FIELD(TYPE, NAME) /* empty */ @@ -158,100 +264,6 @@ RefPtr structuralTransform( return transformer.dispatch(expr); } -// - -class TupleExpr; -class TupleVarDecl; -class VaryingTupleExpr; -class VaryingTupleVarDecl; - - -// The result of lowering a declaration will usually be a declaration, -// but it might also be a "tuple" declaration, in cases where we needed -// to sclarize (or partially scalarize) things to guarantee validity. -struct LoweredDecl -{ - enum class Flavor - { - Decl, // A single declaration (the default case) - Tuple, // A `TupleVarDecl` representing multiple decls - VaryingTuple, // A `VaryingTupleVarDecl` representing multiple decls - }; - - LoweredDecl() - : flavor(Flavor::Decl) - {} - - LoweredDecl(Decl* decl) - : value(decl) - , flavor(Flavor::Decl) - {} - - LoweredDecl(TupleVarDecl* decl) - : value((RefObject*) decl) - , flavor(Flavor::Tuple) - {} - - LoweredDecl(VaryingTupleVarDecl* decl) - : value((RefObject*) decl) - , flavor(Flavor::VaryingTuple) - {} - - Flavor getFlavor() const { return flavor; } - RefObject* getValue() const { return value; } - - Decl* getDecl() const - { - SLANG_ASSERT(getFlavor() == Flavor::Decl); - return (Decl*) value.Ptr(); - } - - TupleVarDecl* getTupleDecl() const - { - SLANG_ASSERT(getFlavor() == Flavor::Tuple); - return (TupleVarDecl*) value.Ptr(); - } - - VaryingTupleVarDecl* getVaryingTupleDecl() const - { - SLANG_ASSERT(getFlavor() == Flavor::VaryingTuple); - return (VaryingTupleVarDecl*) value.Ptr(); - } - - Decl* asDecl() const - { - return (getFlavor() == Flavor::Decl) ? getDecl() : nullptr; - } - - TupleVarDecl* asTupleDecl() const - { - return (getFlavor() == Flavor::Tuple) ? getTupleDecl() : nullptr; - } - - VaryingTupleVarDecl* asVaryingTupleDecl() const - { - return (getFlavor() == Flavor::VaryingTuple) ? getVaryingTupleDecl() : nullptr; - } - -private: - RefPtr value; - Flavor flavor; -}; - -struct LoweredDeclRef -{ -public: - LoweredDecl decl; - RefPtr substitutions; - - LoweredDecl getDecl() { return decl; } - - template - DeclRef As() - { - return DeclRef(decl.getDecl(), substitutions).As(); - } -}; // The result of lowering an exrpession will usually be just a single @@ -321,9 +333,10 @@ struct LoweredExpr return (getFlavor() == Flavor::VaryingTuple) ? getVaryingTupleExpr() : nullptr; } - bool operator!() + // Allow use in boolean contexts + operator void*() { - return !value; + return value.Ptr(); } private: @@ -754,7 +767,7 @@ struct LoweringVisitor RefPtr visitArrayExpressionType(ArrayExpressionType* type) { RefPtr loweredType = Slang::getArrayType( - lowerType(type->BaseType), + lowerType(type->baseType), lowerVal(type->ArrayLength).As()); return loweredType; } @@ -1074,7 +1087,7 @@ struct LoweringVisitor if (auto rightVecType = rightType->As()) { // RHS type was a vector - if (auto leftElemVecType = leftArrayType->BaseType->As()) + if (auto leftElemVecType = leftArrayType->baseType->As()) { // LHS element type was also a vector, so this is a "scalar splat // to array" case. @@ -1102,7 +1115,7 @@ struct LoweringVisitor swizzleExpr->elementIndices[0] = ee; auto convertedArgExpr = convertExprForAssignmentWithFixups( - leftArrayType->BaseType, + leftArrayType->baseType, swizzleExpr); ctorExpr->Arguments.Add(convertedArgExpr); @@ -1222,7 +1235,7 @@ struct LoweringVisitor if (auto rightVecType = rightType->As()) { // RHS type was a vector - if (auto leftElemVecType = leftArrayType->BaseType->As()) + if (auto leftElemVecType = leftArrayType->baseType->As()) { // LHS element type was also a vector, so this is a "scalar splat // to array" case. @@ -1243,7 +1256,7 @@ struct LoweringVisitor // LHS array element RefPtr arrayElemExpr = new IndexExpr(); arrayElemExpr->loc = leftExpr->loc; - arrayElemExpr->type.type = leftArrayType->BaseType; + arrayElemExpr->type.type = leftArrayType->baseType; arrayElemExpr->BaseExpression = leftExpr; arrayElemExpr->IndexExpression = createConstIntExpr(ee); @@ -1495,7 +1508,7 @@ struct LoweringVisitor { if (auto arrayType = type->As()) { - return arrayType->BaseType; + return arrayType->baseType; } return nullptr; } @@ -1702,7 +1715,7 @@ struct LoweringVisitor while (auto arrayType = varType->As()) { - varType = arrayType->BaseType; + varType = arrayType->baseType; } if (auto constantBufferType = varType->As()) @@ -2834,7 +2847,7 @@ struct LoweringVisitor auto type = inType; while (auto arrayType = type->As()) { - type = arrayType->BaseType; + type = arrayType->baseType; } return type; } @@ -2848,7 +2861,7 @@ struct LoweringVisitor { while (auto arrayType = type->As()) { - type = arrayType->BaseType; + type = arrayType->baseType; } if (auto textureTypeBase = type->As()) @@ -3065,7 +3078,7 @@ struct LoweringVisitor arraySpec.elementCount = arrayType->ArrayLength; TupleSecondaryVarInfo subInfo = info; - subInfo.tupleType = arrayType->BaseType; + subInfo.tupleType = arrayType->baseType; subInfo.arraySpecs = &arraySpec; createTupleTypeSecondaryVarDecls(subInfo); return; @@ -3685,7 +3698,7 @@ struct LoweringVisitor { if (auto baseType = type->As()) { - switch (baseType->BaseType) + switch (baseType->baseType) { default: return false; @@ -4108,7 +4121,7 @@ struct LoweringVisitor // heterogeneous stuff... return lowerShaderParameterToGLSLGLobalsRec( arrayInfo, - arrayType->BaseType, + arrayType->baseType, varLayout); } else if (auto declRefType = varType->As()) diff --git a/source/slang/parameter-binding.cpp b/source/slang/parameter-binding.cpp index a00520c05..8cc93fdd2 100644 --- a/source/slang/parameter-binding.cpp +++ b/source/slang/parameter-binding.cpp @@ -413,7 +413,7 @@ RefPtr tryGetEffectiveTypeForGLSLVaryingInput( // Unwrap array type, if prsent if( auto arrayType = type->As() ) { - type = arrayType->BaseType.Ptr(); + type = arrayType->baseType.Ptr(); } } break; @@ -452,7 +452,7 @@ RefPtr tryGetEffectiveTypeForGLSLVaryingOutput( // Unwrap array type, if prsent if( auto arrayType = type->As() ) { - type = arrayType->BaseType.Ptr(); + type = arrayType->baseType.Ptr(); } } break; @@ -1213,13 +1213,13 @@ static RefPtr processEntryPointParameter( auto elementCount = (UInt) GetIntVal(arrayType->ArrayLength); // We use the first element to derive the layout for the element type - auto elementTypeLayout = processEntryPointParameter(context, arrayType->BaseType, state, varLayout); + auto elementTypeLayout = processEntryPointParameter(context, arrayType->baseType, state, varLayout); // We still walk over subsequent elements to make sure they consume resources // as needed for( UInt ii = 1; ii < elementCount; ++ii ) { - processEntryPointParameter(context, arrayType->BaseType, state, nullptr); + processEntryPointParameter(context, arrayType->baseType, state, nullptr); } RefPtr arrayTypeLayout = new ArrayTypeLayout(); diff --git a/source/slang/parameter-binding.h b/source/slang/parameter-binding.h index 66c8053d3..264163974 100644 --- a/source/slang/parameter-binding.h +++ b/source/slang/parameter-binding.h @@ -4,7 +4,7 @@ #include "../core/basic.h" #include "syntax.h" -#include "../../Slang.h" +#include "../../slang.h" namespace Slang { diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 2381682aa..38d9c744d 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -1,4 +1,4 @@ -#include "Parser.h" +#include "parser.h" #include diff --git a/source/slang/profile.cpp b/source/slang/profile.cpp index 4420a722a..6090ddc2e 100644 --- a/source/slang/profile.cpp +++ b/source/slang/profile.cpp @@ -1,5 +1,5 @@ // profile.cpp -#include "Profile.h" +#include "profile.h" namespace Slang { diff --git a/source/slang/reflection.cpp b/source/slang/reflection.cpp index b63240506..5e18e8cfd 100644 --- a/source/slang/reflection.cpp +++ b/source/slang/reflection.cpp @@ -223,7 +223,7 @@ SLANG_API SlangReflectionType* spReflectionType_GetElementType(SlangReflectionTy if(auto arrayType = dynamic_cast(type)) { - return (SlangReflectionType*) arrayType->BaseType.Ptr(); + return (SlangReflectionType*) arrayType->baseType.Ptr(); } else if( auto constantBufferType = dynamic_cast(type)) { @@ -299,7 +299,7 @@ SLANG_API SlangScalarType spReflectionType_GetScalarType(SlangReflectionType* in if(auto basicType = dynamic_cast(type)) { - switch (basicType->BaseType) + switch (basicType->baseType) { #define CASE(BASE, TAG) \ case BaseType::BASE: return SLANG_SCALAR_TYPE_##TAG @@ -330,7 +330,7 @@ SLANG_API SlangResourceShape spReflectionType_GetResourceShape(SlangReflectionTy while(auto arrayType = type->As()) { - type = arrayType->BaseType.Ptr(); + type = arrayType->baseType.Ptr(); } if(auto textureType = type->As()) @@ -363,7 +363,7 @@ SLANG_API SlangResourceAccess spReflectionType_GetResourceAccess(SlangReflection while(auto arrayType = type->As()) { - type = arrayType->BaseType.Ptr(); + type = arrayType->baseType.Ptr(); } if(auto textureType = type->As()) @@ -399,7 +399,7 @@ SLANG_API SlangReflectionType* spReflectionType_GetResourceResultType(SlangRefle while(auto arrayType = type->As()) { - type = arrayType->BaseType.Ptr(); + type = arrayType->baseType.Ptr(); } if (auto textureType = type->As()) @@ -1100,11 +1100,11 @@ static void emitReflectionTypeInfoJSON( { switch( type->getKind() ) { - case SLANG_TYPE_KIND_SAMPLER_STATE: + case slang::TypeReflection::Kind::SamplerState: write(writer, "\"kind\": \"samplerState\""); break; - case SLANG_TYPE_KIND_RESOURCE: + case slang::TypeReflection::Kind::Resource: { auto shape = type->getResourceShape(); auto access = type->getResourceAccess(); @@ -1163,7 +1163,7 @@ static void emitReflectionTypeInfoJSON( } break; - case SLANG_TYPE_KIND_CONSTANT_BUFFER: + case slang::TypeReflection::Kind::ConstantBuffer: write(writer, "\"kind\": \"constantBuffer\""); write(writer, ",\n"); write(writer, "\"elementType\": "); @@ -1172,7 +1172,7 @@ static void emitReflectionTypeInfoJSON( type->getElementType()); break; - case SLANG_TYPE_KIND_TEXTURE_BUFFER: + case slang::TypeReflection::Kind::TextureBuffer: write(writer, "\"kind\": \"textureBuffer\""); write(writer, ",\n"); write(writer, "\"elementType\": "); @@ -1181,7 +1181,7 @@ static void emitReflectionTypeInfoJSON( type->getElementType()); break; - case SLANG_TYPE_KIND_SHADER_STORAGE_BUFFER: + case slang::TypeReflection::Kind::ShaderStorageBuffer: write(writer, "\"kind\": \"shaderStorageBuffer\""); write(writer, ",\n"); write(writer, "\"elementType\": "); @@ -1190,7 +1190,7 @@ static void emitReflectionTypeInfoJSON( type->getElementType()); break; - case SLANG_TYPE_KIND_SCALAR: + case slang::TypeReflection::Kind::Scalar: write(writer, "\"kind\": \"scalar\""); write(writer, ",\n"); emitReflectionScalarTypeInfoJSON( @@ -1198,7 +1198,7 @@ static void emitReflectionTypeInfoJSON( type->getScalarType()); break; - case SLANG_TYPE_KIND_VECTOR: + case slang::TypeReflection::Kind::Vector: write(writer, "\"kind\": \"vector\""); write(writer, ",\n"); write(writer, "\"elementCount\": "); @@ -1210,7 +1210,7 @@ static void emitReflectionTypeInfoJSON( type->getElementType()); break; - case SLANG_TYPE_KIND_MATRIX: + case slang::TypeReflection::Kind::Matrix: write(writer, "\"kind\": \"matrix\""); write(writer, ",\n"); write(writer, "\"rowCount\": "); @@ -1225,7 +1225,7 @@ static void emitReflectionTypeInfoJSON( type->getElementType()); break; - case SLANG_TYPE_KIND_ARRAY: + case slang::TypeReflection::Kind::Array: { auto arrayType = type; write(writer, "\"kind\": \"array\""); @@ -1238,7 +1238,7 @@ static void emitReflectionTypeInfoJSON( } break; - case SLANG_TYPE_KIND_STRUCT: + case slang::TypeReflection::Kind::Struct: { write(writer, "\"kind\": \"struct\",\n"); write(writer, "\"fields\": [\n"); @@ -1274,7 +1274,7 @@ static void emitReflectionTypeLayoutInfoJSON( emitReflectionTypeInfoJSON(writer, typeLayout->getType()); break; - case SLANG_TYPE_KIND_ARRAY: + case slang::TypeReflection::Kind::Array: { auto arrayTypeLayout = typeLayout; auto elementTypeLayout = arrayTypeLayout->getElementTypeLayout(); @@ -1296,7 +1296,7 @@ static void emitReflectionTypeLayoutInfoJSON( } break; - case SLANG_TYPE_KIND_STRUCT: + case slang::TypeReflection::Kind::Struct: { write(writer, "\"kind\": \"struct\",\n"); write(writer, "\"fields\": [\n"); @@ -1316,7 +1316,7 @@ static void emitReflectionTypeLayoutInfoJSON( } break; - case SLANG_TYPE_KIND_CONSTANT_BUFFER: + case slang::TypeReflection::Kind::ConstantBuffer: write(writer, "\"kind\": \"constantBuffer\""); write(writer, ",\n"); write(writer, "\"elementType\": "); @@ -1325,7 +1325,7 @@ static void emitReflectionTypeLayoutInfoJSON( typeLayout->getElementTypeLayout()); break; - case SLANG_TYPE_KIND_TEXTURE_BUFFER: + case slang::TypeReflection::Kind::TextureBuffer: write(writer, "\"kind\": \"textureBuffer\""); write(writer, ",\n"); write(writer, "\"elementType\": "); @@ -1334,7 +1334,7 @@ static void emitReflectionTypeLayoutInfoJSON( typeLayout->getElementTypeLayout()); break; - case SLANG_TYPE_KIND_SHADER_STORAGE_BUFFER: + case slang::TypeReflection::Kind::ShaderStorageBuffer: write(writer, "\"kind\": \"shaderStorageBuffer\""); write(writer, ",\n"); write(writer, "\"elementType\": "); diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp index cf45cbca8..3e526e96c 100644 --- a/source/slang/slang-stdlib.cpp +++ b/source/slang/slang-stdlib.cpp @@ -248,7 +248,7 @@ namespace Slang #define EMIT_LINE_DIRECTIVE() sb << "#line " << (__LINE__+1) << " \"" << path << "\"\n" - #include "core.meta.slang.cpp" + #include "core.meta.slang.h" coreLibraryCode = sb.ProduceString(); return coreLibraryCode; @@ -261,7 +261,7 @@ namespace Slang StringBuilder sb; - #include "hlsl.meta.slang.cpp" + #include "hlsl.meta.slang.h" hlslLibraryCode = sb.ProduceString(); return hlslLibraryCode; @@ -279,7 +279,7 @@ namespace Slang StringBuilder sb; - #include "glsl.meta.slang.cpp" + #include "glsl.meta.slang.h" glslLibraryCode = sb.ProduceString(); return glslLibraryCode; diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index d02f880fd..475802cb1 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -15,7 +15,7 @@ namespace Slang auto basicType = dynamic_cast(type); if (basicType == nullptr) return false; - return basicType->BaseType == BaseType; + return basicType->baseType == this->baseType; } Type* BasicExpressionType::CreateCanonicalType() @@ -28,7 +28,7 @@ namespace Slang { Slang::StringBuilder res; - switch (BaseType) + switch (this->baseType) { case Slang::BaseType::Int: res.Append("int"); @@ -63,21 +63,19 @@ namespace Slang #undef ABSTRACT_SYNTAX_CLASS #define ABSTRACT_SYNTAX_CLASS(NAME, BASE) \ + template<> \ SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl::kClassInfo = { #NAME, &SyntaxClassBase::Impl::kClassInfo, nullptr }; -#define SYNTAX_CLASS(NAME, BASE) \ - void NAME::accept(NAME::Visitor* visitor, void* extra) \ - { visitor->dispatch_##NAME(this, extra); } \ - void* SyntaxClassBase::Impl::createFunc() { return new NAME(); } \ - SyntaxClass NAME::getClass() { return Slang::getClass(); } \ +#define SYNTAX_CLASS(NAME, BASE) \ + void NAME::accept(NAME::Visitor* visitor, void* extra) \ + { visitor->dispatch_##NAME(this, extra); } \ + template<> \ + void* SyntaxClassBase::Impl::createFunc() { return new NAME(); } \ + SyntaxClass NAME::getClass() { return Slang::getClass(); } \ + template<> \ SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl::kClassInfo = { #NAME, &SyntaxClassBase::Impl::kClassInfo, &SyntaxClassBase::Impl::createFunc }; -#include "expr-defs.h" -#include "decl-defs.h" -#include "modifier-defs.h" -#include "stmt-defs.h" -#include "type-defs.h" -#include "val-defs.h" +template<> SyntaxClassBase::ClassInfo const SyntaxClassBase::Impl::kClassInfo = { "RefObject", nullptr, nullptr }; ABSTRACT_SYNTAX_CLASS(NodeBase, RefObject); @@ -94,6 +92,14 @@ ABSTRACT_SYNTAX_CLASS(Expr, SyntaxNode); ABSTRACT_SYNTAX_CLASS(Substitutions, SyntaxNode); +#include "expr-defs.h" +#include "decl-defs.h" +#include "modifier-defs.h" +#include "stmt-defs.h" +#include "type-defs.h" +#include "val-defs.h" + + #include "object-meta-end.h" bool SyntaxClassBase::isSubClassOfImpl(SyntaxClassBase const& super) const @@ -278,11 +284,12 @@ void Type::accept(IValVisitor* visitor, void* extra) auto arrType = type->AsArrayType(); if (!arrType) return false; - return (ArrayLength == arrType->ArrayLength && BaseType->Equals(arrType->BaseType.Ptr())); + return (ArrayLength == arrType->ArrayLength && baseType->Equals(arrType->baseType.Ptr())); } + Type* ArrayExpressionType::CreateCanonicalType() { - auto canonicalElementType = BaseType->GetCanonicalType(); + auto canonicalElementType = baseType->GetCanonicalType(); auto canonicalArrayType = getArrayType( canonicalElementType, ArrayLength); @@ -292,16 +299,16 @@ void Type::accept(IValVisitor* visitor, void* extra) int ArrayExpressionType::GetHashCode() { if (ArrayLength) - return (BaseType->GetHashCode() * 16777619) ^ ArrayLength->GetHashCode(); + return (baseType->GetHashCode() * 16777619) ^ ArrayLength->GetHashCode(); else - return BaseType->GetHashCode(); + return baseType->GetHashCode(); } Slang::String ArrayExpressionType::ToString() { if (ArrayLength) - return BaseType->ToString() + "[" + ArrayLength->ToString() + "]"; + return baseType->ToString() + "[" + ArrayLength->ToString() + "]"; else - return BaseType->ToString() + "[]"; + return baseType->ToString() + "[]"; } // DeclRefType @@ -1115,7 +1122,7 @@ void Type::accept(IValVisitor* visitor, void* extra) auto session = elementType->getSession(); auto arrayType = new ArrayExpressionType(); arrayType->setSession(session); - arrayType->BaseType = elementType; + arrayType->baseType = elementType; arrayType->ArrayLength = elementCount; return arrayType; } @@ -1126,7 +1133,7 @@ void Type::accept(IValVisitor* visitor, void* extra) auto session = elementType->getSession(); auto arrayType = new ArrayExpressionType(); arrayType->setSession(session); - arrayType->BaseType = elementType; + arrayType->baseType = elementType; return arrayType; } diff --git a/source/slang/syntax.h b/source/slang/syntax.h index 2fcfe8d39..8d6a1edbc 100644 --- a/source/slang/syntax.h +++ b/source/slang/syntax.h @@ -168,10 +168,12 @@ namespace Slang return (T*)current; } - void operator++() + void operator++(); + #if 0 { current = Adjust(current->next.Ptr()); } + #endif bool operator!=(Iterator other) { @@ -198,7 +200,8 @@ namespace Slang Iterator begin() { return Iterator(modifiers); } Iterator end() { return Iterator(nullptr); } - static Modifier* Adjust(Modifier* modifier) + static Modifier* Adjust(Modifier* modifier); + #if 0 { Modifier* m = modifier; for (;;) @@ -208,6 +211,7 @@ namespace Slang m = m->next.Ptr(); } } + #endif Modifier* modifiers; }; @@ -445,11 +449,11 @@ namespace Slang } // "dynamic cast" to a more specific declaration reference type - template - DeclRef As() const + template + DeclRef As() const { - DeclRef result; - result.decl = dynamic_cast(decl); + DeclRef result; + result.decl = dynamic_cast(decl); result.substitutions = substitutions; return result; } @@ -904,7 +908,7 @@ namespace Slang // inline BaseType GetVectorBaseType(VectorExpressionType* vecType) { - return vecType->elementType->AsBasicType()->BaseType; + return vecType->elementType->AsBasicType()->baseType; } inline int GetVectorSize(VectorExpressionType* vecType) @@ -1011,6 +1015,28 @@ namespace Slang RefPtr getSamplerStateType( Session* session); + + // Definitions that can't come earlier despite + // being in templates, because gcc/clang get angry. + // + template + void FilteredModifierList::Iterator::operator++() + { + current = Adjust(current->next.Ptr()); + } + // + template + Modifier* FilteredModifierList::Adjust(Modifier* modifier) + { + Modifier* m = modifier; + for (;;) + { + if (!m) return m; + if (dynamic_cast(m)) return m; + m = m->next.Ptr(); + } + } + } // namespace Slang #endif \ No newline at end of file diff --git a/source/slang/type-defs.h b/source/slang/type-defs.h index d556e58e4..7883b5c42 100644 --- a/source/slang/type-defs.h +++ b/source/slang/type-defs.h @@ -76,15 +76,14 @@ END_SYNTAX_CLASS() SYNTAX_CLASS(BasicExpressionType, ArithmeticExpressionType) - FIELD(BaseType, BaseType) + FIELD(BaseType, baseType) RAW( BasicExpressionType() {} BasicExpressionType( Slang::BaseType baseType) - { - BaseType = baseType; - } + : baseType(baseType) + {} virtual Slang::String ToString() override; protected: virtual BasicExpressionType* GetScalarType() override; @@ -283,7 +282,7 @@ SIMPLE_SYNTAX_CLASS(GLSLOutputParameterBlockType, VaryingParameterBlockType) SIMPLE_SYNTAX_CLASS(GLSLShaderStorageBufferType, UniformParameterBlockType) SYNTAX_CLASS(ArrayExpressionType, Type) - SYNTAX_FIELD(RefPtr, BaseType) + SYNTAX_FIELD(RefPtr, baseType) SYNTAX_FIELD(RefPtr, ArrayLength) RAW( diff --git a/source/slang/type-layout.cpp b/source/slang/type-layout.cpp index ec71df37d..27bcbd174 100644 --- a/source/slang/type-layout.cpp +++ b/source/slang/type-layout.cpp @@ -1168,7 +1168,7 @@ SimpleLayoutInfo GetLayoutImpl( else if(auto basicType = type->As()) { return GetSimpleLayoutImpl( - rules->GetScalarLayout(basicType->BaseType), + rules->GetScalarLayout(basicType->baseType), type, rules, outTypeLayout); @@ -1229,7 +1229,7 @@ SimpleLayoutInfo GetLayoutImpl( RefPtr elementTypeLayout; auto elementInfo = GetLayoutImpl( context, - arrayType->BaseType.Ptr(), + arrayType->baseType.Ptr(), outTypeLayout ? &elementTypeLayout : nullptr); // For layout purposes, we treat an unsized array as an array of zero elements. diff --git a/source/slang/vm.cpp b/source/slang/vm.cpp index 70315e701..65ecefc01 100644 --- a/source/slang/vm.cpp +++ b/source/slang/vm.cpp @@ -332,7 +332,7 @@ void dumpVMFrame(VMFrame* vmFrame) fprintf(stderr, "0x%p: ", regData); - fprintf(stderr, "%%%u ", rr); + fprintf(stderr, "%%%u ", (unsigned int) rr); if (name) { fprintf(stderr, "\"%s\" ", name); diff --git a/source/slangc/main.cpp b/source/slangc/main.cpp index da670909d..7c57fa8a9 100644 --- a/source/slangc/main.cpp +++ b/source/slangc/main.cpp @@ -1,11 +1,11 @@ // main.cpp #define SLANG_DYNAMIC -#include "../slang.h" +#include "../../slang.h" SLANG_API void spSetCommandLineCompilerMode(SlangCompileRequest* request); -#include "core/slang-io.h" +#include "../core/slang-io.h" using namespace Slang; diff --git a/tools/render-test/render-d3d11.cpp b/tools/render-test/render-d3d11.cpp index 456278dd2..dc8f11438 100644 --- a/tools/render-test/render-d3d11.cpp +++ b/tools/render-test/render-d3d11.cpp @@ -6,7 +6,7 @@ // In order to use the Slang API, we need to include its header -#include +#include #ifdef _MSC_VER #pragma warning(disable: 4996) diff --git a/tools/slang-generate/main.cpp b/tools/slang-generate/main.cpp index 17fa4edae..eef7d95c7 100644 --- a/tools/slang-generate/main.cpp +++ b/tools/slang-generate/main.cpp @@ -415,7 +415,7 @@ int main( Node* node = readInput(input, inputEnd); char outputPath[1024]; - sprintf(outputPath, "%s.cpp", inputPath); + sprintf(outputPath, "%s.h", inputPath); FILE* outputStream = fopen(outputPath, "w"); -- cgit v1.2.3