From 4fc46c675a8d5a02242852b98c23817172fc7cea Mon Sep 17 00:00:00 2001 From: Aidan Foster Date: Tue, 19 Aug 2025 13:57:54 -0700 Subject: [PATCH 01/11] Add Sphinx CI --- .github/workflows/sphinx-build-test.yml | 49 +++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 .github/workflows/sphinx-build-test.yml diff --git a/.github/workflows/sphinx-build-test.yml b/.github/workflows/sphinx-build-test.yml new file mode 100644 index 00000000000..e0d508606aa --- /dev/null +++ b/.github/workflows/sphinx-build-test.yml @@ -0,0 +1,49 @@ +name: Build Sphinx Documentation + +on: + pull_request: + branches: [master] + +jobs: + sphinx-build: + runs-on: ubuntu-latest + steps: + - name: Checkout shader-slang.github.io main branch + uses: actions/checkout@v4 + with: + repository: shader-slang/shader-slang.github.io + ref: main + path: docs-site + + - name: Checkout slang PR branch as submodule + uses: actions/checkout@v4 + with: + ref: ${{ github.head_ref }} + repository: ${{ github.head_repository.full_name }} + path: docs-site/docs/external/slang + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + cache: 'pip' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r docs-site/requirements.txt + + - name: Build Sphinx Documentation + run: | + cd docs-site/docs + # Run Sphinx build to catch issues + # -D build_toctree=True enables toctree processing to verify all docs are included + python -m sphinx -b html . _build/html + + - name: Check for broken links to external sites + run: | + cd docs-site/docs + # Run linkcheck builder to find broken links + python -m sphinx -b linkcheck . _build/linkcheck + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 26eca3041f27f78a60a517d3d7e2caa7d14d55fa Mon Sep 17 00:00:00 2001 From: Aidan Foster Date: Tue, 19 Aug 2025 14:10:02 -0700 Subject: [PATCH 02/11] Treat warnings as errors --- .github/workflows/sphinx-build-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/sphinx-build-test.yml b/.github/workflows/sphinx-build-test.yml index e0d508606aa..0b3949b788a 100644 --- a/.github/workflows/sphinx-build-test.yml +++ b/.github/workflows/sphinx-build-test.yml @@ -25,8 +25,8 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.10' - cache: 'pip' + python-version: "3.10" + cache: "pip" - name: Install dependencies run: | @@ -38,7 +38,7 @@ jobs: cd docs-site/docs # Run Sphinx build to catch issues # -D build_toctree=True enables toctree processing to verify all docs are included - python -m sphinx -b html . _build/html + python -m sphinx -W -b html . _build/html - name: Check for broken links to external sites run: | From 28e2590ace44680ffea3ef8bdfe6077b581c16a5 Mon Sep 17 00:00:00 2001 From: Aidan Foster Date: Tue, 19 Aug 2025 14:33:44 -0700 Subject: [PATCH 03/11] Use fork for website, temporarily --- .github/workflows/sphinx-build-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sphinx-build-test.yml b/.github/workflows/sphinx-build-test.yml index 0b3949b788a..25f489fa8be 100644 --- a/.github/workflows/sphinx-build-test.yml +++ b/.github/workflows/sphinx-build-test.yml @@ -11,8 +11,8 @@ jobs: - name: Checkout shader-slang.github.io main branch uses: actions/checkout@v4 with: - repository: shader-slang/shader-slang.github.io - ref: main + repository: aidanfnv/shader-slang.github.io + ref: fix/sphinx-warnings path: docs-site - name: Checkout slang PR branch as submodule From 0fd5ad2aa6c37e05345995f5a7d5fb961ec995d9 Mon Sep 17 00:00:00 2001 From: Aidan Foster Date: Tue, 19 Aug 2025 14:47:51 -0700 Subject: [PATCH 04/11] Recurse submodules, remove slang dir if present --- .github/workflows/sphinx-build-test.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/sphinx-build-test.yml b/.github/workflows/sphinx-build-test.yml index 25f489fa8be..25a200638f6 100644 --- a/.github/workflows/sphinx-build-test.yml +++ b/.github/workflows/sphinx-build-test.yml @@ -14,6 +14,10 @@ jobs: repository: aidanfnv/shader-slang.github.io ref: fix/sphinx-warnings path: docs-site + submodules: recursive + + - name: Remove existing slang directory if present + run: rm -rf docs-site/docs/external/slang - name: Checkout slang PR branch as submodule uses: actions/checkout@v4 @@ -21,6 +25,7 @@ jobs: ref: ${{ github.head_ref }} repository: ${{ github.head_repository.full_name }} path: docs-site/docs/external/slang + submodules: recursive - name: Set up Python uses: actions/setup-python@v5 From a5b4c5957601cf20454ea41d51d09d24072aa15f Mon Sep 17 00:00:00 2001 From: Aidan Foster Date: Tue, 19 Aug 2025 14:51:48 -0700 Subject: [PATCH 05/11] Replace non-existent "cmd" lexer with "batch" --- docs/building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/building.md b/docs/building.md index b6e18ad2512..b135b956a5d 100644 --- a/docs/building.md +++ b/docs/building.md @@ -76,7 +76,7 @@ For non-Windows platforms ``` For Windows -```cmd +```batch emsdk.bat install latest emsdk.bat activate latest ``` From 4ebb9da7aeed0d67125e53374604d96734220ac6 Mon Sep 17 00:00:00 2001 From: Aidan Foster Date: Tue, 19 Aug 2025 15:04:50 -0700 Subject: [PATCH 06/11] Remove "C" lexer from non-C codeblock --- docs/design/autodiff/ir-overview.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/design/autodiff/ir-overview.md b/docs/design/autodiff/ir-overview.md index dd5f44f53ab..73ce06c9fbb 100644 --- a/docs/design/autodiff/ir-overview.md +++ b/docs/design/autodiff/ir-overview.md @@ -643,7 +643,8 @@ for (int i = 0; i < 10; i++) ``` After AD passes, this results in the following code: -```C + +``` //// Primal context pass. From 08747203b922216908a639fbf2610ec54496cd78 Mon Sep 17 00:00:00 2001 From: Aidan Foster Date: Tue, 19 Aug 2025 15:05:25 -0700 Subject: [PATCH 07/11] Replace non-existent "slang" lexer with "hlsl" --- docs/design/stdlib-intrinsics.md | 9 ++++--- docs/user-guide/03-convenience-features.md | 27 ++++++++++++------- docs/user-guide/06-interfaces-generics.md | 6 +++-- docs/user-guide/a1-03-obfuscation.md | 12 ++++++--- .../user-guide/a2-01-spirv-target-specific.md | 3 ++- .../user-guide/a2-02-metal-target-specific.md | 15 +++++++---- 6 files changed, 48 insertions(+), 24 deletions(-) diff --git a/docs/design/stdlib-intrinsics.md b/docs/design/stdlib-intrinsics.md index 2ea50cd541f..267683a9e33 100644 --- a/docs/design/stdlib-intrinsics.md +++ b/docs/design/stdlib-intrinsics.md @@ -25,7 +25,8 @@ The `.meta.slang` files look largely like Slang source files, but their contents As an example, to produce an an array with values 0 to 9 we could write... -```slang + +```hlsl // Slang code ${{{{ @@ -142,7 +143,8 @@ Used to specify the IR opcode associated with a type. The IR opcode is listed as As an example from the core module -```slang + +```hlsl __magic_type(HLSLByteAddressBufferType) __intrinsic_type($(kIROp_HLSLByteAddressBufferType)) struct ByteAddressBuffer @@ -204,7 +206,8 @@ Used to specify the GLSL version number that is required for the subsequent decl For example -```slang + +```hlsl __glsl_version(430) ``` diff --git a/docs/user-guide/03-convenience-features.md b/docs/user-guide/03-convenience-features.md index 3f659015b54..ab325a01fcd 100644 --- a/docs/user-guide/03-convenience-features.md +++ b/docs/user-guide/03-convenience-features.md @@ -454,7 +454,8 @@ specialized shader variant when it is not used by the shader. For example, a common use case is to define the vertex shader output / fragment shader input: -```slang + +```hlsl interface IVertex { property float3 position{get;} @@ -493,7 +494,8 @@ struct Vertex : IVertex In this example, `Vertex` type is parameterized on `hasNormal` and `hasColor`. If `hasNormal` is false, the `m_normal` field will be eliminated in the target code, allowing a specialized vertex shader to declare minimum output fields. For example, a vertex shader can be defined as follows: -```slang + +```hlsl [shader("vertex")] Vertex vertMain(VertexIn inputVertex) { @@ -604,7 +606,8 @@ to access the global descriptor heap or resource array in order to obtain the ac are not opaque handles, `DescriptorHandle` maps to `T` and will have the same size and alignment defined by the target. `DescriptorHandle` is declared as: -```slang + +```hlsl struct DescriptorHandle where T:IOpaqueDescriptor {} ``` where `IOpaqueDescriptor` is an interface implemented by all resource types, including textures, @@ -614,7 +617,8 @@ You may also write `Texture2D.Handle` as a short-hand of `DescriptorHandle` supports `operator *`, `operator ->`, and can implicitly convert to `T`, for example: -```slang + +```hlsl uniform StructuredBuffer> textures; uniform int textureIndex; @@ -683,7 +687,8 @@ Default behavior assigns binding-indicies based on descriptor types: Users can override the default behavior of convering from bindless handle to resource handle, by providing a `getDescriptorFromHandle` in user code. For example: -```slang + +```hlsl // All texture and buffer handles are defined in descriptor set 100. [vk::binding(0, 100)] __DynamicResource<__DynamicResourceKind.General> resourceHandles[]; @@ -713,7 +718,8 @@ Think about providing `getDescriptorFromHandle` as a way to override `operator-> The `IOpaqueDescriptor` interface is defined as: -```slang + +```hlsl interface IOpaqueDescriptor { /// The kind of the descriptor. @@ -726,7 +732,8 @@ The user can call `defaultGetDescriptorFromHandle` function from their implement `getDescriptorFromHandle` to dispatch to the default behavior. Additionally, `defaultGetDescriptorFromHandle()` takes an optional argument whose type is `constexpr BindlessDescriptorOptions`. This parameter allows to specify alternative standard presets for how bindless-indexes are assigned. Note that this is currently only relevant to SPIRV: - ```slang + +```hlsl public enum BindlessDescriptorOptions { None = 0, /// Bind assuming regular binding model rules. @@ -765,7 +772,8 @@ public enum BindlessDescriptorOptions The `kind` and `descriptorAccess` constants allows user code to fetch resources from different locations depending on the type and access of the resource being requested. The `DescriptorKind` and `DescriptorAccess` enums are defined as: -```slang + +```hlsl enum DescriptorKind { Unknown, /// Unknown descriptor kind. @@ -791,7 +799,8 @@ enum DescriptorAccess By default, the value of a `DescriptorHandle` object is assumed to be dynamically uniform across all execution threads. If this is not the case, the user is required to mark the `DescriptorHandle` as `nonuniform` *immediately* before dereferencing it: -```slang + +```hlsl void test(DescriptorHandle t) { nonuniform(t)->Sample(...); diff --git a/docs/user-guide/06-interfaces-generics.md b/docs/user-guide/06-interfaces-generics.md index 30efbada14b..e5215d2ef53 100644 --- a/docs/user-guide/06-interfaces-generics.md +++ b/docs/user-guide/06-interfaces-generics.md @@ -48,7 +48,8 @@ In this case, the definition of `MyType` must satisfy the requirements from both Interface methods can have a default implementation, which will be used if a conforming type doesn't provide an overriding implementation. For example: -```slang + +```hlsl interface IFoo { int getVal() { return 0; } @@ -60,7 +61,8 @@ struct MyType : IFoo {} A concrete type that provides its overriding implementation to an interface method requirement that has a default implementation must be explicitly marked as 'override'. For example: -```slang + +```hlsl struct MyType2 : IFoo { // Explicitly mark `getVal` as `override` is needed diff --git a/docs/user-guide/a1-03-obfuscation.md b/docs/user-guide/a1-03-obfuscation.md index bafafee9a02..37fbed64395 100644 --- a/docs/user-guide/a1-03-obfuscation.md +++ b/docs/user-guide/a1-03-obfuscation.md @@ -72,7 +72,8 @@ This means that `-r` is *NOT* enough to be able access the functionality of the For example, in "module.slang" -```slang + +```hlsl struct Thing { int a; @@ -87,7 +88,8 @@ int foo(Thing thing) In the source that uses this module -```slang + +```hlsl // This is fragile - needs match the definition in "module.slang" struct Thing { @@ -115,7 +117,8 @@ void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID) If the type `Thing` is only used opaquely then it would only be necessary to declare that it exists. For example in "module-opaque.slang" -```slang + +```hlsl struct Thing { int a; @@ -135,7 +138,8 @@ int foo(Thing thing) In the source that uses this module -```slang + +```hlsl // We can just declare Thing exists, as its usage is opaque. struct Thing; int foo(Thing thing); diff --git a/docs/user-guide/a2-01-spirv-target-specific.md b/docs/user-guide/a2-01-spirv-target-specific.md index 0f64a5e1b4a..87ca598b8b6 100644 --- a/docs/user-guide/a2-01-spirv-target-specific.md +++ b/docs/user-guide/a2-01-spirv-target-specific.md @@ -111,7 +111,8 @@ This matches the behavior of D3D where `SV_InstanceID` and `SV_VertexID` starts If you need direct access to `InstanceIndex` and `VertexIndex` values, use `SV_VulkanInstanceID` and `SV_VulkanVertexID` semantic names. These are supported for all targets except HLSL. Alternatively you can use parameters with `SV_InstanceID`(or `SV_VertexID`) and `SV_StartInstanceLocation`(or `SV_StartVertexLocation`) semantics: -```slang + +```hlsl void myVertexShader( uint instanceID : SV_InstanceID, // InstanceIndex - BaseInstance uint baseInstance : SV_StartInstanceLocation) // BaseInstance diff --git a/docs/user-guide/a2-02-metal-target-specific.md b/docs/user-guide/a2-02-metal-target-specific.md index 5d3e336db96..55ef29ec50a 100644 --- a/docs/user-guide/a2-02-metal-target-specific.md +++ b/docs/user-guide/a2-02-metal-target-specific.md @@ -132,7 +132,8 @@ the translation of matrix operations to maintain correct semantics: Mesh shaders can be targeted using the following types and syntax. The same as task/mesh shaders generally in Slang. -```slang + +```hlsl [outputtopology("triangle")] [numthreads(12, 1, 1)] void meshMain( @@ -161,7 +162,8 @@ using namespace metal; `ParameterBlock` values are translated into _Argument Buffers_ potentially containing nested resources. For example, this Slang code... -```slang + +```hlsl struct MyParameters { int x; @@ -194,7 +196,8 @@ struct MyParameters When targeting Metal, top-level nested struct parameters are automatically flattened. For example: -```slang + +```hlsl struct NestedStruct { float2 uv; @@ -223,7 +226,8 @@ struct InputStruct Non-struct return values from entry points are automatically wrapped in a struct with appropriate semantics. For example: -```slang + +```hlsl float4 main() : SV_Target { return float4(1,2,3,4); @@ -254,7 +258,8 @@ automatically performs the following conversions: For example: -```slang + +```hlsl RWTexture2D tex; tex[coord] = float2(1,2); // Automatically expanded to float4(1,2,0,0) ``` From bf08df0d96addf77cdd3c598533539a5f6bff2c8 Mon Sep 17 00:00:00 2001 From: Aidan Foster Date: Tue, 19 Aug 2025 15:16:26 -0700 Subject: [PATCH 08/11] Replace non-existent "metal" lexer with "csharp" --- docs/user-guide/a2-02-metal-target-specific.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/a2-02-metal-target-specific.md b/docs/user-guide/a2-02-metal-target-specific.md index 55ef29ec50a..2ea84ce856b 100644 --- a/docs/user-guide/a2-02-metal-target-specific.md +++ b/docs/user-guide/a2-02-metal-target-specific.md @@ -303,7 +303,7 @@ const int a = 2; Translates to: -```metal +```csharp constant int fc_a_0 [[function_constant(7)]]; constant int a_0 = is_function_constant_defined(fc_a_0) ? fc_a_0 : 2; ``` From ab966c2c83a2dee62dfd608e70e314ca41b6348f Mon Sep 17 00:00:00 2001 From: Aidan Foster Date: Tue, 19 Aug 2025 15:17:02 -0700 Subject: [PATCH 09/11] Remove "hlsl" lexer from codeblocks that it will not work for --- docs/design/stdlib-intrinsics.md | 8 ++++---- docs/language-reference/06-statements.md | 3 ++- docs/user-guide/a1-04-interop.md | 3 ++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/design/stdlib-intrinsics.md b/docs/design/stdlib-intrinsics.md index 267683a9e33..46f08d4cc6e 100644 --- a/docs/design/stdlib-intrinsics.md +++ b/docs/design/stdlib-intrinsics.md @@ -25,8 +25,8 @@ The `.meta.slang` files look largely like Slang source files, but their contents As an example, to produce an an array with values 0 to 9 we could write... - -```hlsl + +``` // Slang code ${{{{ @@ -143,8 +143,8 @@ Used to specify the IR opcode associated with a type. The IR opcode is listed as As an example from the core module - -```hlsl + +``` __magic_type(HLSLByteAddressBufferType) __intrinsic_type($(kIROp_HLSLByteAddressBufferType)) struct ByteAddressBuffer diff --git a/docs/language-reference/06-statements.md b/docs/language-reference/06-statements.md index 5c3b77ad457..7620bb45f6b 100644 --- a/docs/language-reference/06-statements.md +++ b/docs/language-reference/06-statements.md @@ -213,7 +213,8 @@ Compile-Time For Statement A _compile-time for statement_ is used as an alternative to preprocessor techniques for loop unrolling. It looks like: -```hlsl + +``` $for( in Range(, )) ``` diff --git a/docs/user-guide/a1-04-interop.md b/docs/user-guide/a1-04-interop.md index 279325b407a..82c821a5852 100644 --- a/docs/user-guide/a1-04-interop.md +++ b/docs/user-guide/a1-04-interop.md @@ -111,7 +111,8 @@ The strings in `__requirePrelude` are deduplicated: the same prelude string will ## Managing Cross-Platform Code If you are defining an intrinsic function that maps to multiple targets in different ways, you can use `__target_switch` construct to manage the target-specific definitions. For example, here is a snippet from the Slang core module that defines `getRealtimeClock`: -```hlsl + +``` [__requiresNVAPI] __glsl_extension(GL_EXT_shader_realtime_clock) uint2 getRealtimeClock() From 0ed2a46ce477348fa838982b8a283a534d694b9a Mon Sep 17 00:00:00 2001 From: Aidan Foster Date: Tue, 19 Aug 2025 15:45:25 -0700 Subject: [PATCH 10/11] Generate core module reference for doc testing --- .github/workflows/sphinx-build-test.yml | 31 +++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/.github/workflows/sphinx-build-test.yml b/.github/workflows/sphinx-build-test.yml index 25a200638f6..e8d6d0e70b6 100644 --- a/.github/workflows/sphinx-build-test.yml +++ b/.github/workflows/sphinx-build-test.yml @@ -27,6 +27,37 @@ jobs: path: docs-site/docs/external/slang submodules: recursive + - name: Backup existing core-module-reference index.md + run: | + if [ -f docs-site/docs/external/core-module-reference/index.md ]; then + cp docs-site/docs/external/core-module-reference/index.md /tmp/core-module-index.md + fi + + - name: Remove existing core-module-reference directory + run: rm -rf docs-site/docs/external/core-module-reference + + - name: Install build dependencies + run: | + sudo apt-get update + sudo apt-get install -y ninja-build libx11-dev + + - name: Build slangc from PR + run: | + cd docs-site/docs/external/slang + # Disable LLVM for faster build since we only need slangc for docs + cmake --preset default --fresh -DSLANG_SLANG_LLVM_FLAVOR=DISABLE + cmake --build --preset release --target slangc + + - name: Generate core module reference from PR + run: | + cd docs-site/docs/external + mkdir -p core-module-reference + cd core-module-reference + # Generate the core module documentation + ../slang/build/Release/bin/slangc -compile-core-module -doc + # Restore the original index.md + cp /tmp/core-module-index.md index.md + - name: Set up Python uses: actions/setup-python@v5 with: From 6346fc2fec8647707a2e2d3b6235b5f572e232db Mon Sep 17 00:00:00 2001 From: Aidan Foster Date: Tue, 19 Aug 2025 15:57:42 -0700 Subject: [PATCH 11/11] Use .md in core module reference, use MD anchors --- source/slang/slang-doc-markdown-writer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/slang/slang-doc-markdown-writer.cpp b/source/slang/slang-doc-markdown-writer.cpp index 2a215d6bd6b..ab5ca0f04d6 100644 --- a/source/slang/slang-doc-markdown-writer.cpp +++ b/source/slang/slang-doc-markdown-writer.cpp @@ -114,19 +114,19 @@ void DocMarkdownWriter::_appendAsBullets( auto& out = *m_builder; for (const auto& value : values) { - out << "#### "; if (value.decl) { // Add anchor ID for the decl. if (as(value.decl)) { - out << " getName()) << "\">"; + out << "(typeparam-" << getText(value.decl->getName()) << ")=\n"; } else { - out << " getName()) << "\">"; + out << "(decl-" << getText(value.decl->getName()) << ")=\n"; } } + out << "#### "; const String& name = value.name; auto path = findLinkForToken(m_currentPage, name); if (name.getLength()) @@ -2160,7 +2160,7 @@ String DocMarkdownWriter::translateToMarkdownWithLinks(String text, bool strictC sb.append(Path::getPathWithoutExt(Path::getRelativePath( Path::getParentDirectory(m_currentPage->path), page->path))); - sb.append(".html"); + sb.append(".md"); if (sectionName.getLength()) sb << "#" << sectionName; sb.append(")");