summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-core-module-textures.cpp
diff options
context:
space:
mode:
authorJay Kwak <82421531+jkwak-work@users.noreply.github.com>2024-10-25 15:59:17 -0700
committerGitHub <noreply@github.com>2024-10-25 15:59:17 -0700
commitd8969d87dcc9eea3f186a0c93c5e48d3d1659e05 (patch)
treea7c17a8d8ce08bdd1551ba4815de809a4d1783f6 /source/slang/slang-core-module-textures.cpp
parent4bad669bbc5ec3ff77321f083c59cde87eb10229 (diff)
Replace stdlib with core-module on files and projects (#5411)
This commit renames the files and projects to prefer "core-module" over "stdlib". The directory name `source/slang-stdlib` needs to be renamed too, and there will be another commit for it soon.
Diffstat (limited to 'source/slang/slang-core-module-textures.cpp')
-rw-r--r--source/slang/slang-core-module-textures.cpp505
1 files changed, 505 insertions, 0 deletions
diff --git a/source/slang/slang-core-module-textures.cpp b/source/slang/slang-core-module-textures.cpp
new file mode 100644
index 000000000..a74a954d5
--- /dev/null
+++ b/source/slang/slang-core-module-textures.cpp
@@ -0,0 +1,505 @@
+#include "slang-core-module-textures.h"
+#include <spirv/unified1/spirv.h>
+
+#define EMIT_LINE_DIRECTIVE() sb << "#line " << (__LINE__+1) << " \"slang-core-module-textures.cpp\"\n"
+
+namespace Slang
+{
+
+// Concatenate anything which can be passed to a StringBuilder
+template<typename... Ts>
+String cat(const Ts&... xs)
+{
+ return (StringBuilder{} << ... << xs);
+};
+
+//
+// Utilities
+//
+
+const auto indentWidth = 4;
+static const char spaces[] = " ";
+static_assert(SLANG_COUNT_OF(spaces) % indentWidth == 1);
+
+struct BraceScope
+{
+ BraceScope(const char*& i, StringBuilder& sb, const char* end = "\n")
+ :i(i), sb(sb), end(end)
+ {
+ // If we hit this assert, it means that we are indenting too deep and
+ // need more spaces in 'spaces' above.
+ SLANG_ASSERT(i != spaces);
+ sb << i << "{\n";
+ i -= indentWidth;
+ }
+ ~BraceScope()
+ {
+ // If we hit this assert, it means that we've got a bug unindenting
+ // more than we've indented.
+ SLANG_ASSERT(*i != '\0');
+ i += indentWidth;
+ sb << i << "}" << end;
+ }
+ const char*& i;
+ StringBuilder& sb;
+ const char* end;
+};
+
+TextureTypeInfo::TextureTypeInfo(
+ BaseTextureShapeInfo const& base,
+ bool isArray,
+ bool isMultisample,
+ bool isShadow,
+ StringBuilder& inSB,
+ String const& inPath)
+ : base(base)
+ , isArray(isArray)
+ , isMultisample(isMultisample)
+ , isShadow(isShadow)
+ , sb(inSB)
+ , path(inPath)
+{
+ i = spaces + SLANG_COUNT_OF(spaces) - 1;
+}
+
+void TextureTypeInfo::writeFuncBody(
+ const char* funcName,
+ const String& glsl,
+ const String& cuda,
+ const String& spirvDefault,
+ const String& spirvRWDefault,
+ const String& spirvCombined,
+ const String& metal,
+ const String& wgsl)
+{
+ BraceScope funcScope{i, sb};
+ {
+ sb << i << "__target_switch\n";
+ BraceScope switchScope{i, sb};
+ sb << i << "case cpp:\n";
+ sb << i << "case hlsl:\n";
+ sb << i << "__intrinsic_asm \"." << funcName << "\";\n";
+ if(glsl.getLength())
+ {
+ sb << i << "case glsl:\n";
+ if (glsl.startsWith("if"))
+ sb << glsl;
+ else
+ sb << i << "__intrinsic_asm \"" << glsl << "\";\n";
+ }
+ if(cuda.getLength())
+ {
+ sb << i << "case cuda:\n";
+ sb << i << "__intrinsic_asm \"" << cuda << "\";\n";
+ }
+ if (metal.getLength())
+ {
+ sb << i << "case metal:\n";
+ sb << i << "__intrinsic_asm \"" << metal << "\";\n";
+ }
+ if (spirvDefault.getLength() && spirvCombined.getLength())
+ {
+ sb << i << "case spirv:\n";
+ sb << i << "if (access == " << kStdlibResourceAccessReadWrite << ")\n";
+ sb << i << "return spirv_asm\n";
+ {
+ BraceScope spirvRWScope{ i, sb, ";\n" };
+ sb << spirvRWDefault << "\n";
+ }
+ sb << i << "else if (isCombined != 0)\n";
+ sb << i << "{\n";
+ {
+ sb << i << "return spirv_asm\n";
+ BraceScope spirvCombinedScope{i, sb, ";\n"};
+ sb << spirvCombined << "\n";
+ }
+ sb << i << "}\n";
+ sb << i << "else\n";
+ sb << i << "{\n";
+ {
+ sb << i << "return spirv_asm\n";
+ BraceScope spirvDefaultScope{i, sb, ";\n"};
+ sb << spirvDefault << "\n";
+ }
+ sb << i << "}\n";
+ }
+ if (wgsl.getLength())
+ {
+ sb << i << "case wgsl:\n";
+ sb << i << "__intrinsic_asm \"" << wgsl << "\";\n";
+ }
+ }
+}
+
+void TextureTypeInfo::writeFuncWithSig(
+ const char* funcName,
+ const String& sig,
+ const String& glsl,
+ const String& spirvDefault,
+ const String& spirvRWDefault,
+ const String& spirvCombined,
+ const String& cuda,
+ const String& metal,
+ const String& wgsl,
+ const ReadNoneMode readNoneMode)
+{
+ if (readNoneMode == ReadNoneMode::Always)
+ sb << i << "[__readNone]\n";
+ sb << i << "[ForceInline]\n";
+ sb << i << sig << "\n";
+ writeFuncBody(funcName, glsl, cuda, spirvDefault, spirvRWDefault, spirvCombined, metal, wgsl);
+ sb << "\n";
+}
+
+void TextureTypeInfo::writeFunc(
+ const char* returnType,
+ const char* funcName,
+ const String& params,
+ const String& glsl,
+ const String& spirvDefault,
+ const String& spirvRWDefault,
+ const String& spirvCombined,
+ const String& cuda,
+ const String& metal,
+ const String& wgsl,
+ const ReadNoneMode readNoneMode)
+{
+ writeFuncWithSig(
+ funcName,
+ cat(returnType, " ", funcName, "(", params, ")"),
+ glsl,
+ spirvDefault,
+ spirvRWDefault,
+ spirvCombined,
+ cuda,
+ metal,
+ wgsl,
+ readNoneMode
+ );
+}
+
+void TextureTypeInfo::writeGetDimensionFunctions()
+{
+ static const char* kComponentNames[]{ "x", "y", "z", "w" };
+
+ SlangResourceShape baseShape = base.baseShape;
+
+ // `GetDimensions`
+ const char* dimParamTypes[] = { "out float ", "out int ", "out uint " };
+ const char* dimParamTypesInner[] = { "float", "int", "uint" };
+ for (int tid = 0; tid < 3; tid++)
+ {
+ auto t = dimParamTypes[tid];
+ auto rawT = dimParamTypesInner[tid];
+
+ for (int includeMipInfo = 0; includeMipInfo < 2; ++includeMipInfo)
+ {
+ if (includeMipInfo && isMultisample)
+ {
+ continue;
+ }
+
+ int sizeDimCount = 0;
+ StringBuilder params;
+ int paramCount = 0;
+
+ StringBuilder metal;
+ const char* metalMipLevel = "0";
+
+ StringBuilder wgsl;
+ wgsl << "{";
+
+ if (includeMipInfo)
+ {
+ ++paramCount;
+ params << "uint mipLevel,";
+
+ if (baseShape != SLANG_TEXTURE_1D)
+ metalMipLevel = "$1";
+ }
+
+ switch (baseShape)
+ {
+ case SLANG_TEXTURE_1D:
+ ++paramCount;
+ params << t << "width";
+ metal << "(*($" << String(paramCount) << ") = $0.get_width(" << String(metalMipLevel) << ")),";
+ wgsl << "($" << String(paramCount) << ") = textureDimensions($0" << (includeMipInfo ? ", $1" : "") << ");";
+
+ sizeDimCount = 1;
+ break;
+
+ case SLANG_TEXTURE_2D:
+ case SLANG_TEXTURE_CUBE:
+ ++paramCount;
+ params << t << "width,";
+ metal << "(*($" << String(paramCount) << ") = $0.get_width(" << String(metalMipLevel) << ")),";
+ wgsl << "var dim = textureDimensions($0" << (includeMipInfo ? ", $1" : "") << ");";
+ wgsl << "($" << String(paramCount) << ") = dim.x;";
+
+ ++paramCount;
+ params << t << "height";
+ metal << "(*($" << String(paramCount) << ") = $0.get_height(" << String(metalMipLevel) << ")),";
+ wgsl << "($" << String(paramCount) << ") = dim.y;";
+
+ sizeDimCount = 2;
+ break;
+
+ case SLANG_TEXTURE_3D:
+ ++paramCount;
+ params << t << "width,";
+ metal << "(*($" << String(paramCount) << ") = $0.get_width(" << String(metalMipLevel) << ")),";
+ wgsl << "var dim = textureDimensions($0" << (includeMipInfo ? ", $1" : "") << ");";
+ wgsl << "($" << String(paramCount) << ") = dim.x;";
+
+ ++paramCount;
+ params << t << "height,";
+ metal << "(*($" << String(paramCount) << ") = $0.get_height(" << String(metalMipLevel) << ")),";
+ wgsl << "($" << String(paramCount) << ") = dim.y;";
+
+ ++paramCount;
+ params << t << "depth";
+ metal << "(*($" << String(paramCount) << ") = $0.get_depth(" << String(metalMipLevel) << ")),";
+ wgsl << "($" << String(paramCount) << ") = dim.z;";
+
+ sizeDimCount = 3;
+ break;
+
+ default:
+ assert(!"unexpected");
+ break;
+ }
+
+ if (isArray)
+ {
+ ++sizeDimCount;
+ ++paramCount;
+ params << ", " << t << "elements";
+ metal << "(*($" << String(paramCount) << ") = $0.get_array_size()),";
+ wgsl << "($" << String(paramCount) << ") = textureNumLayers($0);";
+ }
+
+ if (isMultisample)
+ {
+ ++paramCount;
+ params << ", " << t << "sampleCount";
+ metal << "(*($" << String(paramCount) << ") = $0.get_num_samples()),";
+ wgsl << "($" << String(paramCount) << ") = textureNumSamples($0);";
+ }
+
+ if (includeMipInfo)
+ {
+ ++paramCount;
+ params << ", " << t << "numberOfLevels";
+ metal << "(*($" << String(paramCount) << ") = $0.get_num_mip_levels()),";
+ wgsl << "($" << String(paramCount) << ") = textureNumLevels($0);";
+ }
+
+ metal.reduceLength(metal.getLength() - 1); // drop the last comma
+ wgsl << "}";
+
+ StringBuilder glsl;
+ {
+ auto emitIntrinsic = [&](UnownedStringSlice funcName, bool useLodStr)
+ {
+ int aa = 1;
+ StringBuilder opStrSB;
+ opStrSB << " = " << funcName << "($0";
+ if (useLodStr)
+ {
+ String lodStr = ", 0";
+ if (includeMipInfo)
+ {
+ int mipLevelArg = aa++;
+ lodStr = ", int($";
+ lodStr.append(mipLevelArg);
+ lodStr.append(")");
+ }
+ opStrSB << lodStr;
+ }
+ auto opStr = opStrSB.produceString();
+ int cc = 0;
+ switch (baseShape)
+ {
+ case SLANG_TEXTURE_1D:
+ glsl << "($" << aa++ << opStr << ")";
+ if (isArray)
+ {
+ glsl << ".x";
+ }
+ glsl << ")";
+ cc = 1;
+ break;
+
+ case SLANG_TEXTURE_2D:
+ case SLANG_TEXTURE_CUBE:
+ glsl << "($" << aa++ << opStr << ").x)";
+ glsl << ", ($" << aa++ << opStr << ").y)";
+ cc = 2;
+ break;
+
+ case SLANG_TEXTURE_3D:
+ glsl << "($" << aa++ << opStr << ").x)";
+ glsl << ", ($" << aa++ << opStr << ").y)";
+ glsl << ", ($" << aa++ << opStr << ").z)";
+ cc = 3;
+ break;
+
+ default:
+ SLANG_UNEXPECTED("unhandled resource shape");
+ break;
+ }
+
+ if (isArray)
+ {
+ glsl << ", ($" << aa++ << opStr << ")." << kComponentNames[cc] << ")";
+ }
+
+ if (isMultisample)
+ {
+ glsl << ", ($" << aa++ << " = textureSamples($0))";
+ }
+
+ if (includeMipInfo)
+ {
+ glsl << ", ($" << aa++ << " = textureQueryLevels($0))";
+ }
+ };
+ glsl << "if (access == " << kStdlibResourceAccessReadOnly << ") __intrinsic_asm \"";
+ emitIntrinsic(toSlice("textureSize"), !isMultisample);
+ glsl << "\";\n";
+ glsl << "__intrinsic_asm \"";
+ emitIntrinsic(toSlice("imageSize"), false);
+ glsl << "\";\n";
+ }
+
+ // SPIRV ASM generation
+ auto generateSpirvAsm = [&](StringBuilder& spirv, bool isRW, UnownedStringSlice imageVar)
+ {
+ spirv << "%vecSize:$$uint";
+ if (sizeDimCount > 1) spirv << sizeDimCount;
+ spirv << " = ";
+ if (isMultisample || isRW)
+ spirv << "OpImageQuerySize " << imageVar << ";";
+ else
+ spirv << "OpImageQuerySizeLod " << imageVar <<" $0;";
+
+ auto convertAndStore = [&](UnownedStringSlice uintSourceVal, const char* destParam)
+ {
+ if (UnownedStringSlice(rawT) == "uint")
+ {
+ spirv << "OpStore &" << destParam << " %" << uintSourceVal << ";";
+ }
+ else
+ {
+ if (UnownedStringSlice(rawT) == "int")
+ {
+ spirv << "%c_" << uintSourceVal << " : $$" << rawT << " = OpBitcast %" << uintSourceVal << "; ";
+ }
+ else
+ {
+ spirv << "%c_" << uintSourceVal << " : $$" << rawT << " = OpConvertUToF %" << uintSourceVal << "; ";
+ }
+ spirv << "OpStore &" << destParam << "%c_" << uintSourceVal << ";";
+ }
+ };
+ auto extractSizeComponent = [&](int componentId, const char* destParam)
+ {
+ String elementVal = String("_") + destParam;
+ if (sizeDimCount == 1)
+ {
+ spirv << "%" << elementVal << " : $$uint = OpCopyObject %vecSize; ";
+ }
+ else
+ {
+ spirv << "%" << elementVal << " : $$uint = OpCompositeExtract %vecSize " << componentId << "; ";
+ }
+ convertAndStore(elementVal.getUnownedSlice(), destParam);
+ };
+ switch (baseShape)
+ {
+ case SLANG_TEXTURE_1D:
+ extractSizeComponent(0, "width");
+ break;
+
+ case SLANG_TEXTURE_2D:
+ case SLANG_TEXTURE_CUBE:
+ extractSizeComponent(0, "width");
+ extractSizeComponent(1, "height");
+ break;
+
+ case SLANG_TEXTURE_3D:
+ extractSizeComponent(0, "width");
+ extractSizeComponent(1, "height");
+ extractSizeComponent(2, "depth");
+ break;
+
+ default:
+ assert(!"unexpected");
+ break;
+ }
+
+ if (isArray)
+ {
+ extractSizeComponent(sizeDimCount - 1, "elements");
+ }
+
+ if (isMultisample)
+ {
+ spirv << "%_sampleCount : $$uint = OpImageQuerySamples" << imageVar << ";";
+ convertAndStore(UnownedStringSlice("_sampleCount"), "sampleCount");
+ }
+
+ if (includeMipInfo)
+ {
+ spirv << "%_levelCount : $$uint = OpImageQueryLevels" << imageVar << ";";
+ convertAndStore(UnownedStringSlice("_levelCount"), "numberOfLevels");
+ }
+ };
+ StringBuilder spirvCombined;
+ {
+ spirvCombined << "OpCapability ImageQuery; ";
+ spirvCombined << "%image:__imageType(this) = OpImage $this; ";
+ generateSpirvAsm(spirvCombined, false, toSlice("%image"));
+ }
+
+ StringBuilder spirvDefault;
+ {
+ spirvDefault << "OpCapability ImageQuery; ";
+ generateSpirvAsm(spirvDefault, false, toSlice("$this"));
+ }
+
+ StringBuilder spirvRWDefault;
+ {
+ spirvRWDefault << "OpCapability ImageQuery; ";
+ generateSpirvAsm(spirvRWDefault, true, toSlice("$this"));
+ }
+
+ sb << " __glsl_version(450)\n";
+ sb << " __glsl_extension(GL_EXT_samplerless_texture_functions)\n";
+
+ sb << " [require(cpp";
+ if (glsl.getLength()) sb << "_glsl";
+ sb << "_hlsl";
+ if (metal.getLength()) sb << "_metal";
+ if (spirvDefault.getLength() && spirvCombined.getLength()) sb << "_spirv";
+ if (wgsl.getLength()) sb << "_wgsl";
+ sb << ", texture_sm_4_1)]\n";
+
+ writeFunc(
+ "void",
+ "GetDimensions",
+ params,
+ glsl,
+ spirvDefault,
+ spirvRWDefault,
+ spirvCombined,
+ "",
+ metal,
+ wgsl,
+ ReadNoneMode::Always);
+ }
+ }
+}
+
+}