diff options
| author | Tim Foley <tfoley@nvidia.com> | 2017-09-07 14:35:07 -0700 |
|---|---|---|
| committer | Tim Foley <tfoley@nvidia.com> | 2017-09-11 09:50:56 -0700 |
| commit | 14137cbd2ddd7deebcdf8cc85c30d534bec8e40b (patch) | |
| tree | 5f9b010837de0c78f2f96e59388bf76e4cbd8575 /source/slang/glsl.meta.slang.cpp | |
| parent | 0e566a63f0bafb7def65521315e9f19a2bc79e34 (diff) | |
Initial work on boilerplate code generator
The goal here is to get the Slang "standard library" code out of string literals and into something a bit more like an actual code file.
This is handled by having a `slang-generate` tool that can translate a "template" file that mixes raw Slang code (or any language we want to generate...) with generation logic that is implemented in C++ (currently).
This work isn't final by any stretch of the imagination, but it moves a lot of code and not merging it ASAP will complicate other changes.
My expectation is that the generator tool will be beefed up on an as-needed basis, to get our stdlib code working.
Similarly, the stdlib code does not really take advantage of the new approach as much as it could. That is something we can clean up along the way as we do modifications of the stdlib.
Diffstat (limited to 'source/slang/glsl.meta.slang.cpp')
| -rw-r--r-- | source/slang/glsl.meta.slang.cpp | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/source/slang/glsl.meta.slang.cpp b/source/slang/glsl.meta.slang.cpp new file mode 100644 index 000000000..e43a51ea9 --- /dev/null +++ b/source/slang/glsl.meta.slang.cpp @@ -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<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(mul) vector<T,N> operator*(vector<T,N> x, T y);\n"; +sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(mul) vector<T,N> operator*(T x, vector<T,N> y);\n"; + +// scalar-matrix and matrix-scalar +sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op(mul) matrix<T,N,M> operator*(matrix<T,N,M> x, T y);\n"; +sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M :int> __intrinsic_op(mul) matrix<T,N,M> operator*(T x, matrix<T,N,M> y);\n"; + +// vector-vector (dot product) +sb << "__generic<T : __BuiltinArithmeticType, let N : int> __intrinsic_op(dot) T operator*(vector<T,N> x, vector<T,N> y);\n"; + +// vector-matrix +sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(mulVectorMatrix) vector<T,M> operator*(vector<T,N> x, matrix<T,N,M> y);\n"; + +// matrix-vector +sb << "__generic<T : __BuiltinArithmeticType, let N : int, let M : int> __intrinsic_op(mulMatrixVector) vector<T,N> operator*(matrix<T,N,M> x, vector<T,M> y);\n"; + +// matrix-matrix +sb << "__generic<T : __BuiltinArithmeticType, let R : int, let N : int, let C : int> __intrinsic_op(mulMatrixMatrix) matrix<T,R,C> operator*(matrix<T,R,N> x, matrix<T,N,C> 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<T> "; + sb << "__magic_type(TextureSampler," << int(readFlavor) << ") struct "; + sb << "__sampler" << name; + sb << " {};\n"; + + sb << "__generic<T> "; + sb << "__magic_type(Texture," << int(readFlavor) << ") struct "; + sb << "__texture" << name; + sb << " {};\n"; + + sb << "__generic<T> "; + 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<T> __magic_type(GLSLInputParameterBlockType) struct __GLSLInputParameterBlock {};\n"; +sb << "__generic<T> __magic_type(GLSLOutputParameterBlockType) struct __GLSLOutputParameterBlock {};\n"; +sb << "__generic<T> __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 << ""; |
