@carbonenginejs/runtime-resource 0.11.1 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CjsResMan.js +4 -4
- package/dist/CjsResMan.js.map +1 -1
- package/dist/_virtual/_rollupPluginBabelHelpers.js +1 -4
- package/dist/_virtual/_rollupPluginBabelHelpers.js.map +1 -1
- package/dist/format/CjsByteReader.js +310 -0
- package/dist/format/CjsByteReader.js.map +1 -0
- package/dist/format/CjsByteWriter.js +242 -0
- package/dist/format/CjsByteWriter.js.map +1 -0
- package/dist/format/CjsFormatError.js +41 -0
- package/dist/format/CjsFormatError.js.map +1 -0
- package/dist/format/CjsStringTable.js +268 -0
- package/dist/format/CjsStringTable.js.map +1 -0
- package/dist/format/carbonEffect/CjsCarbonEffectReader.js +361 -0
- package/dist/format/carbonEffect/CjsCarbonEffectReader.js.map +1 -0
- package/dist/format/carbonEffect/CjsCarbonEffectWriter.js +373 -0
- package/dist/format/carbonEffect/CjsCarbonEffectWriter.js.map +1 -0
- package/dist/format/carbonEffect/carbonDescriptionFromPortable.js +372 -0
- package/dist/format/carbonEffect/carbonDescriptionFromPortable.js.map +1 -0
- package/dist/format/carbonEffect/carbonEffectBackendBlock.js +427 -0
- package/dist/format/carbonEffect/carbonEffectBackendBlock.js.map +1 -0
- package/dist/format/carbonEffect/carbonEffectRecords.js +955 -0
- package/dist/format/carbonEffect/carbonEffectRecords.js.map +1 -0
- package/dist/format/compareUtf8.js +36 -0
- package/dist/format/compareUtf8.js.map +1 -0
- package/dist/format/index.js +11 -0
- package/dist/format/index.js.map +1 -0
- package/dist/formats/bnk/CjsBnkFormat.js +18 -2
- package/dist/formats/bnk/CjsBnkFormat.js.map +1 -1
- package/dist/formats/bnk/core/eventAction.js +305 -0
- package/dist/formats/bnk/core/eventAction.js.map +1 -0
- package/dist/formats/bnk/core/graph.js +3 -6
- package/dist/formats/bnk/core/graph.js.map +1 -1
- package/dist/formats/bnk/core/helpers.js +62 -11
- package/dist/formats/bnk/core/helpers.js.map +1 -1
- package/dist/formats/bnk/core/nodeBase.js +532 -0
- package/dist/formats/bnk/core/nodeBase.js.map +1 -0
- package/dist/formats/bnk/core/sfxNodes.js +632 -0
- package/dist/formats/bnk/core/sfxNodes.js.map +1 -0
- package/dist/formats/bnk/core/soundbanksInfo.js +59 -51
- package/dist/formats/bnk/core/soundbanksInfo.js.map +1 -1
- package/dist/formats/gr2/CjsGr2Format.js +256 -13
- package/dist/formats/gr2/CjsGr2Format.js.map +1 -1
- package/dist/formats/gr2/core/helpers.js +15 -15
- package/dist/formats/gr2/core/helpers.js.map +1 -1
- package/dist/formats/gr2/core/json.js +1 -1
- package/dist/formats/gr2/core/json.js.map +1 -1
- package/dist/formats/gr2/core/targets.js +1 -1
- package/dist/formats/gr2/core/targets.js.map +1 -1
- package/dist/formats/gr2/index.js +0 -1
- package/dist/formats/gr2/index.js.map +1 -1
- package/dist/formats/hlsl/core/HlslReader.js +7 -257
- package/dist/formats/hlsl/core/HlslReader.js.map +1 -1
- package/dist/formats/hlsl/core/analysis.js +1 -1
- package/dist/formats/hlsl/core/carbonDescriptionToRuntime.js +781 -0
- package/dist/formats/hlsl/core/carbonDescriptionToRuntime.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/resources/HlslEffectRes.js +21 -1
- package/dist/formats/hlsl/core/tr2/resources/HlslEffectRes.js.map +1 -1
- package/dist/formats/hlsl/index.js +1 -0
- package/dist/formats/hlsl/index.js.map +1 -1
- package/dist/formats/index.js +3 -6
- package/dist/formats/index.js.map +1 -1
- package/dist/formats/webgl/core/cewg/CewgPackage.js +2 -1
- package/dist/formats/webgl/core/cewg/CewgPackage.js.map +1 -1
- package/dist/formats/webgl/core/cewg/binary.js +11 -93
- package/dist/formats/webgl/core/cewg/binary.js.map +1 -1
- package/dist/formats/webgl/core/effectPackage.js +4 -1
- package/dist/formats/webgl/core/effectPackage.js.map +1 -1
- package/dist/formats/webgl/core/errors.js +3 -3
- package/dist/formats/webgl/core/errors.js.map +1 -1
- package/dist/formats/webgpu/CjsWebgpuFormat.js +4 -23
- package/dist/formats/webgpu/CjsWebgpuFormat.js.map +1 -1
- package/dist/formats/webgpu/core/buildCarbonEffectContainer.js +197 -0
- package/dist/formats/webgpu/core/buildCarbonEffectContainer.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/CewgpuContainer.js +368 -0
- package/dist/formats/webgpu/core/cewgpu/CewgpuContainer.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/containerViews.js +355 -0
- package/dist/formats/webgpu/core/cewgpu/containerViews.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/validateContainer.js +90 -0
- package/dist/formats/webgpu/core/cewgpu/validateContainer.js.map +1 -0
- package/dist/formats/webgpu/core/effectBackendBodySet.js +21 -20
- package/dist/formats/webgpu/core/effectBackendBodySet.js.map +1 -1
- package/dist/formats/webgpu/core/helpers.js +87 -92
- package/dist/formats/webgpu/core/helpers.js.map +1 -1
- package/dist/formats/webgpu/core/ir/analyzeRegisterValues.js +14 -13
- package/dist/formats/webgpu/core/ir/analyzeRegisterValues.js.map +1 -1
- package/dist/formats/webgpu/core/ir/inferValueTypes.js +10 -8
- package/dist/formats/webgpu/core/ir/inferValueTypes.js.map +1 -1
- package/dist/formats/webgpu/core/packageEffect.js +94 -9
- package/dist/formats/webgpu/core/packageEffect.js.map +1 -1
- package/dist/formats/webgpu/core/packageMetadata.js +10 -1
- package/dist/formats/webgpu/core/packageMetadata.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js +17 -15
- package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/buildWgslBindingPlan.js +13 -12
- package/dist/formats/webgpu/core/wgsl/buildWgslBindingPlan.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/buildWgslSet.js +9 -8
- package/dist/formats/webgpu/core/wgsl/buildWgslSet.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/lowerComputeProgram.js +23 -22
- package/dist/formats/webgpu/core/wgsl/lowerComputeProgram.js.map +1 -1
- package/dist/formats/webgpu/core/wgsl/selectionPlans.js +46 -44
- package/dist/formats/webgpu/core/wgsl/selectionPlans.js.map +1 -1
- package/dist/resource/CjsResource.js +700 -684
- package/dist/resource/CjsResource.js.map +1 -1
- package/dist/resource/Tr2LightProfileRes.js +18 -27
- package/dist/resource/Tr2LightProfileRes.js.map +1 -1
- package/dist/resource/audio/CjsAudioBufferRes.js +2 -2
- package/dist/resource/audio/CjsAudioBufferRes.js.map +1 -1
- package/dist/resource/audio/CjsAudioRes.js +2 -2
- package/dist/resource/audio/CjsAudioRes.js.map +1 -1
- package/dist/resource/geometry/TriGeometryRes.js +605 -586
- package/dist/resource/geometry/TriGeometryRes.js.map +1 -1
- package/dist/resource/geometry/granny/Tr2GrannyStateRes.js +21 -30
- package/dist/resource/geometry/granny/Tr2GrannyStateRes.js.map +1 -1
- package/dist/resource/geometry/granny/TriGrannyRes.js +21 -30
- package/dist/resource/geometry/granny/TriGrannyRes.js.map +1 -1
- package/dist/resource/shader/Tr2EffectRes.js +9 -7
- package/dist/resource/shader/Tr2EffectRes.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialArea.js +5 -3
- package/dist/resource/shader/Tr2MaterialArea.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialMesh.js +4 -2
- package/dist/resource/shader/Tr2MaterialMesh.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialRes.js +5 -3
- package/dist/resource/shader/Tr2MaterialRes.js.map +1 -1
- package/dist/resource/shader/Tr2Shader.js +26 -21
- package/dist/resource/shader/Tr2Shader.js.map +1 -1
- package/dist/resource/shader/Tr2ShaderPermutation.js +8 -6
- package/dist/resource/shader/Tr2ShaderPermutation.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectDefine.js +5 -3
- package/dist/resource/shader/reflection/Tr2EffectDefine.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectDescription.js +5 -3
- package/dist/resource/shader/reflection/Tr2EffectDescription.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectLibrary.js +17 -15
- package/dist/resource/shader/reflection/Tr2EffectLibrary.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectParameterAnnotation.js +11 -9
- package/dist/resource/shader/reflection/Tr2EffectParameterAnnotation.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectResource.js +8 -6
- package/dist/resource/shader/reflection/Tr2EffectResource.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectStageInput.js +15 -13
- package/dist/resource/shader/reflection/Tr2EffectStageInput.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectTechnique.js +7 -5
- package/dist/resource/shader/reflection/Tr2EffectTechnique.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2Pass.js +11 -9
- package/dist/resource/shader/reflection/Tr2Pass.js.map +1 -1
- package/dist/resource/shader/sampler/Tr2SamplerSetup.js +8 -6
- package/dist/resource/shader/sampler/Tr2SamplerSetup.js.map +1 -1
- package/dist/resource/texture/CjsTextureArrayRes.js +400 -411
- package/dist/resource/texture/CjsTextureArrayRes.js.map +1 -1
- package/dist/resource/texture/Tr2ImageRes.js +99 -95
- package/dist/resource/texture/Tr2ImageRes.js.map +1 -1
- package/dist/resource/texture/TriTextureRes.js +312 -273
- package/dist/resource/texture/TriTextureRes.js.map +1 -1
- package/docs/README.md +13 -1
- package/docs/architecture.md +3 -3
- package/docs/concepts/resource-lifecycle.md +9 -2
- package/docs/concepts/shader-resource-model.md +114 -0
- package/docs/concepts/writing-an-engine-adapter.md +115 -0
- package/docs/formats/README.md +24 -1
- package/docs/formats/carbon-effect-container.md +452 -0
- package/docs/formats/dxbc/README.md +68 -0
- package/docs/formats/dxbc/architecture.md +80 -0
- package/docs/formats/dxbc/reference/api.md +77 -0
- package/docs/formats/dxbc/reference/classes/README.md +9 -0
- package/docs/formats/dxbc/reference/decoded-output.md +122 -0
- package/docs/formats/gr2.md +3 -4
- package/docs/formats/hlsl/README.md +54 -0
- package/docs/formats/hlsl/architecture.md +67 -0
- package/docs/formats/hlsl/guides/hydrating-json-output.md +62 -0
- package/docs/formats/hlsl/guides/reading-effects.md +64 -0
- package/docs/formats/hlsl/reference/advanced-analysis.md +66 -0
- package/docs/formats/hlsl/reference/api.md +98 -0
- package/docs/formats/hlsl/reference/classes/README.md +11 -0
- package/docs/formats/hlsl/reference/json-graph.md +100 -0
- package/docs/formats/hlsl/reference/portable-reflection.md +141 -0
- package/docs/formats/provenance.md +32 -17
- package/docs/formats/webgl/README.md +57 -0
- package/docs/formats/webgl/architecture.md +70 -0
- package/docs/formats/webgl/carbon-constant-layouts.md +326 -0
- package/docs/formats/webgl/decl-io.md +1234 -0
- package/docs/formats/webgl/effect-reflection.md +127 -0
- package/docs/formats/webgl/memory-structured.md +871 -0
- package/docs/formats/webgl/reference/classes/README.md +9 -0
- package/docs/formats/webgl/texture-sample.md +964 -0
- package/docs/formats/webgpu/README.md +84 -0
- package/docs/formats/webgpu/architecture.md +96 -0
- package/docs/formats/webgpu/formats/cewgpu.md +216 -0
- package/docs/formats/webgpu/guides/effect-packaging.md +191 -0
- package/docs/formats/webgpu/reference/api.md +197 -0
- package/docs/formats/webgpu/reference/classes/README.md +9 -0
- package/docs/formats/webgpu/reference/wgsl-compatibility.md +1543 -0
- package/docs/formats/wwise.md +45 -4
- package/docs/reference/classes/core.md +80 -0
- package/docs/reference/classes/formats.md +24 -34
- package/docs/reference/events.md +25 -0
- package/docs/reference/motherlode-cache.md +22 -8
- package/docs/reference/workers.md +5 -5
- package/docs/roadmap.md +61 -41
- package/format-notices/bnk/NOTICE +5 -4
- package/format-notices/webgl/NOTICE +1 -1
- package/package.json +2 -1
- package/dist/formats/gr2/core/CjsFormatGr2.js +0 -273
- package/dist/formats/gr2/core/CjsFormatGr2.js.map +0 -1
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackage.js +0 -415
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackage.js.map +0 -1
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackageBuilder.js +0 -100
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackageBuilder.js.map +0 -1
- package/dist/formats/webgpu/core/cewgpu/binary.js +0 -93
- package/dist/formats/webgpu/core/cewgpu/binary.js.map +0 -1
- package/dist/formats/webgpu/core/cewgpu/tags.js +0 -17
- package/dist/formats/webgpu/core/cewgpu/tags.js.map +0 -1
- package/dist/formats/webgpu/core/effectPackageValidation.js +0 -1078
- package/dist/formats/webgpu/core/effectPackageValidation.js.map +0 -1
|
@@ -0,0 +1,871 @@
|
|
|
1
|
+
# DXBC → GLSL ES 3.00 Lowering Spec: Memory-Structured Family
|
|
2
|
+
|
|
3
|
+
Status: Evolving
|
|
4
|
+
Scope: `@carbonenginejs/runtime-resource/formats/webgl` structured-memory lowering
|
|
5
|
+
Audience: Shader translator maintainers and reviewers
|
|
6
|
+
Summary: Defines bounded WebGL2 adaptations for DXBC structured-memory operations.
|
|
7
|
+
|
|
8
|
+
Family key: `memory-structured`
|
|
9
|
+
Target: GLSL ES 3.00 (WebGL2), vertex + pixel stages only (no compute, no SSBOs).
|
|
10
|
+
Register model: every DXBC register is stored by the emitter as a `float` `vec4`; all
|
|
11
|
+
integer/unsigned reads and writes go through `floatBitsToInt` / `floatBitsToUint` /
|
|
12
|
+
`intBitsToFloat` / `uintBitsToFloat` at the use site, mirroring HLSLcc's own
|
|
13
|
+
`GetBitcastOp` (`vendor/HLSLcc/src/toGLSLOperand.cpp:327-353`) and
|
|
14
|
+
`AddOpAssignToDestWithMask` (`vendor/HLSLcc/src/toGLSLInstruction.cpp:28-153`)
|
|
15
|
+
machinery, which HLSLcc itself falls back to whenever static data-type analysis is
|
|
16
|
+
unavailable (exactly the reflection-stripped situation this fork runs in per
|
|
17
|
+
`vendor/HLSLcc/CARBONENGINEJS-FORK.md:34-52`).
|
|
18
|
+
|
|
19
|
+
Corpus counts (450k-instruction sweep, 1611 EVE Online DX11 effects):
|
|
20
|
+
|
|
21
|
+
| Opcode | Count | Stage reality |
|
|
22
|
+
|---|---:|---|
|
|
23
|
+
| `ld_structured` | 4014 | vs (BoneTransforms skinning) + ps (LightBuffer/LightIndexBuffer-style tbuffer reads) |
|
|
24
|
+
| `store_structured` | 930 | compute-only in D3D11 (requires a UAV write target); **not observed as reachable in vs/ps stages actually shipped to WebGL2** — see per-opcode note |
|
|
25
|
+
| `store_uav_typed` | 642 | compute-only in practice for this corpus (UAV write) |
|
|
26
|
+
| `sync` | 183 | compute-only (`sync` only has meaning with `dcl_thread_group`) |
|
|
27
|
+
| `ld_raw` | 54 | no confirmed vs/ps corpus example found (see per-opcode note); same SSBO problem as `ld_structured` if it does appear in vs/ps |
|
|
28
|
+
| `store_raw` | 54 | compute-only in practice (RWByteAddressBuffer write) |
|
|
29
|
+
| `atomic_iadd` | 27 | **confirmed present in a pixel shader** (`lensflareoccludert.sm_depth`, `stageName: "pixel"` in `dx11-instruction-coverage.json`'s `initialCandidateOpcodeExamples`) — not compute-only, see per-opcode note |
|
|
30
|
+
| `imm_atomic_iadd` | 24 | compute-only (UAV atomic with previous-value return) |
|
|
31
|
+
| `ld_uav_typed` | 18 | compute-only in this corpus — sampled instance is `measureexposure.sm_depth` (tone-mapping luminance compute pass), **not** `lensflareoccludert` (that file's confirmed opcode is `atomic_iadd`/`dcl_unordered_access_view_typed`, per `TRANSPILING-GAPS.md:100-114`); see per-opcode note |
|
|
32
|
+
| `imm_atomic_exch` | 9 | compute-only |
|
|
33
|
+
| `atomic_umax` | 6 | compute-only |
|
|
34
|
+
| `atomic_umin` | 3 | compute-only |
|
|
35
|
+
| `bufinfo` | 0 | not observed in this corpus; specified for completeness only |
|
|
36
|
+
|
|
37
|
+
**Central WebGL2 constraint** (governs every opcode below): GLSL ES 3.00 has **no
|
|
38
|
+
shader storage buffers** (`buffer` blocks require `#version 310 es` or GL 4.3+), **no
|
|
39
|
+
image load/store types** (`image2D`/`imageLoad`/`imageStore` require ES 3.10+), and
|
|
40
|
+
**no atomic-memory built-ins outside compute shaders** (`atomicAdd`/`imageAtomicAdd`
|
|
41
|
+
etc. and `barrier()`/`memoryBarrier()` are ES 3.10 compute-shader built-ins, not part
|
|
42
|
+
of the ES 3.00 vertex/fragment built-in set). Every HLSLcc GLSL template shown below
|
|
43
|
+
is therefore **reference material for what desktop/Vulkan/Metal HLSLcc emits**, not
|
|
44
|
+
directly compilable WebGL2 output. The one opcode with a proven, shipping WebGL2
|
|
45
|
+
lowering is `ld_structured` restricted to the `BoneTransforms` skinning case, via the
|
|
46
|
+
package-time `cb3` rewrite described in its section below.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Shared machinery referenced by this family
|
|
51
|
+
|
|
52
|
+
- `HaveUnsignedTypes(eLang)` and `HaveBitEncodingOps(eLang)`
|
|
53
|
+
(`vendor/HLSLcc/src/internal_includes/languages.h:156-180`) both return `1` for
|
|
54
|
+
every target except `LANG_ES_100`/`LANG_120`. `LANG_ES_300` (this project's
|
|
55
|
+
target) has unsigned integer types and bit-encoding intrinsics
|
|
56
|
+
(`floatBitsToInt`/`floatBitsToUint`/`intBitsToFloat`/`uintBitsToFloat`) available,
|
|
57
|
+
so all the `TO_FLAG_UNSIGNED_INTEGER` / bitcast branches below are live for our
|
|
58
|
+
target.
|
|
59
|
+
- `AddAssignToDest` / `AddAssignPrologue`
|
|
60
|
+
(`vendor/HLSLcc/src/toGLSLInstruction.cpp:155-171`) write the destination operand,
|
|
61
|
+
the write mask, `= `, and the correct number of constructor/bitcast open-parens;
|
|
62
|
+
`AddAssignPrologue` closes them and appends `;\n`. This is the generic
|
|
63
|
+
"assign-with-implicit-bitcast" pattern the emitter must reproduce for `ld_structured`,
|
|
64
|
+
`ld_raw`, `ld_uav_typed`, and `bufinfo`.
|
|
65
|
+
- `_sat` (saturate) is applied **generically, after the main switch**, only to
|
|
66
|
+
operand 0 (`vendor/HLSLcc/src/toGLSLInstruction.cpp:4821-4844`): it re-clamps
|
|
67
|
+
`dest = clamp(dest, 0.0, 1.0)` (with an Adreno `min(max(dest,0.0),1.0)` workaround
|
|
68
|
+
path gated behind `#ifdef UNITY_ADRENO_ES3`, since `eTargetLanguage == LANG_ES_300`
|
|
69
|
+
triggers the workaround branch). This only matters for opcodes that write a
|
|
70
|
+
register destination — i.e. `ld_structured`, `ld_raw`, `ld_uav_typed`, `bufinfo`,
|
|
71
|
+
`imm_atomic_*` (previous-value destination). Store/`sync`/non-`imm_` atomics have
|
|
72
|
+
no float destination and DXBC does not encode `_sat` for them in practice.
|
|
73
|
+
- Structured/raw buffer declaration (`DeclareBufferVariable`,
|
|
74
|
+
`vendor/HLSLcc/src/toGLSLDeclaration.cpp:1027-1092`) is the HLSLcc reference
|
|
75
|
+
declaration these instructions index into:
|
|
76
|
+
```glsl
|
|
77
|
+
struct t0_type { uint[<stride/4>] value; };
|
|
78
|
+
layout(std430, binding = N) readonly buffer t0 { t0_type t0_buf[]; };
|
|
79
|
+
```
|
|
80
|
+
(raw buffers use `uint t0_buf[]` / `int t0_buf[]` directly, no wrapper struct,
|
|
81
|
+
selected by `HaveUnsignedTypes`). This declaration is unusable in GLSL ES 3.00 —
|
|
82
|
+
documented here only because the per-instruction `t0_buf[...]` indexing expression
|
|
83
|
+
it feeds is the exact text pattern the package-time `cb3` rewrite (see
|
|
84
|
+
`ld_structured`) pattern-matches against.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## `ld_structured` (4014 instances) — highest priority in this family
|
|
89
|
+
|
|
90
|
+
### Semantics
|
|
91
|
+
Loads a structured-buffer element: given a structure index (operand 1) and a
|
|
92
|
+
byte offset within the structure (operand 2), reads one or more 32-bit components
|
|
93
|
+
from resource operand 3 (a `t#`/`u#` structured buffer) into the destination
|
|
94
|
+
register, per D3D11 `ld_structured` semantics (index-then-byte-offset addressing
|
|
95
|
+
into an array of fixed-stride structures).
|
|
96
|
+
|
|
97
|
+
### GLSL lowering — A. HLSLcc reference (desktop/Vulkan/Metal SSBO path)
|
|
98
|
+
`TranslateShaderStorageLoad`, case `OPCODE_LD_STRUCTURED`
|
|
99
|
+
(`vendor/HLSLcc/src/toGLSLInstruction.cpp:1585-1683`, dispatched at
|
|
100
|
+
`toGLSLInstruction.cpp:4256-4264`). Operands: `psDest=asOperands[0]`,
|
|
101
|
+
`psSrcAddr=asOperands[1]` (struct index), `psSrcByteOff=asOperands[2]` (byte
|
|
102
|
+
offset), `psSrc=asOperands[3]` (resource).
|
|
103
|
+
|
|
104
|
+
For each destination component `c` present in the destination write mask:
|
|
105
|
+
```glsl
|
|
106
|
+
<bitcast_open><resourceName>_buf[<structIndexExpr>].value[(<byteOffExpr> >> 2u) + <swz>u]<bitcast_close>
|
|
107
|
+
```
|
|
108
|
+
where `<swz>` is `psSrc->aui32Swizzle[c]` if the resource operand carries an
|
|
109
|
+
explicit swizzle (`OPERAND_4_COMPONENT_SWIZZLE_MODE`), else `c` itself
|
|
110
|
+
(`toGLSLInstruction.cpp:1673`) — i.e. the *resource* operand's own swizzle can
|
|
111
|
+
remap which dword of the structure element component `c` reads from. All such
|
|
112
|
+
per-component expressions are joined by `AddAssignToDest`/constructor into:
|
|
113
|
+
```glsl
|
|
114
|
+
dest.mask = <ctor>(comp0, comp1, ...);
|
|
115
|
+
```
|
|
116
|
+
(`toGLSLInstruction.cpp:1623-1682`).
|
|
117
|
+
|
|
118
|
+
`<bitcast_open>`/`<bitcast_close>` depend on `destDataType = psDest->GetDataType()`
|
|
119
|
+
(`toGLSLInstruction.cpp:1642-1654`):
|
|
120
|
+
- `SVT_FLOAT` → `uintBitsToFloat(...)` (since `HaveBitEncodingOps` is true for ES
|
|
121
|
+
3.00); the code falls back to `float(...)` only for pre-bit-encoding targets.
|
|
122
|
+
- `SVT_INT`/`SVT_INT16`/`SVT_INT12` → `int(...)`.
|
|
123
|
+
- `SVT_UINT` → no wrapper at all (`addedBitcast` stays `0`) because the backing
|
|
124
|
+
`t0_type.value` array element type is always `uint` — "always uint array atm"
|
|
125
|
+
(`toGLSLInstruction.cpp:1641`).
|
|
126
|
+
|
|
127
|
+
The struct-index operand is translated with **both** `TO_FLAG_UNSIGNED_INTEGER |
|
|
128
|
+
TO_FLAG_INTEGER` set simultaneously (`toGLSLInstruction.cpp:1664`) — reproduce
|
|
129
|
+
this by picking whichever the index operand's own declared type implies (uint by
|
|
130
|
+
default on ES 3.00). The byte-offset operand's flag (`srcOffFlag`) is
|
|
131
|
+
`TO_FLAG_UNSIGNED_INTEGER` unless the target lacks unsigned types or the operand's
|
|
132
|
+
own `SVT_INT`/`SVT_INT16`/`SVT_INT12` type forces `TO_FLAG_INTEGER`
|
|
133
|
+
(`toGLSLInstruction.cpp:1618-1621`); when unsigned, both the `>> 2` and the `+
|
|
134
|
+
<swz>` component addend get a trailing `u` suffix (`toGLSLInstruction.cpp:1669-1675`).
|
|
135
|
+
|
|
136
|
+
### GLSL lowering — B. WebGL2 `cb3` joint-matrix rewrite contract (the shipping path)
|
|
137
|
+
This is the **only** `ld_structured` lowering this emitter must actually produce
|
|
138
|
+
runnable WebGL2 GLSL for, restricted to the `BoneTransforms` skinning case
|
|
139
|
+
(vertex stage). It is a two-stage pipeline:
|
|
140
|
+
|
|
141
|
+
1. Emit HLSLcc's reference SSBO GLSL exactly as in section A (this project's
|
|
142
|
+
HLSLcc fork already tolerates missing `RDEF` bindings for
|
|
143
|
+
`dcl_resource_structured` by falling back to the DXBC declaration's encoded
|
|
144
|
+
stride — see `CARBONENGINEJS-FORK.md:41-44` and
|
|
145
|
+
`TRANSPILING-GAPS.md:51-54`), producing text of the exact shape:
|
|
146
|
+
```glsl
|
|
147
|
+
struct t0_type { uint[1] value; };
|
|
148
|
+
layout(std430, binding = 0) readonly buffer t0 { t0_type t0_buf[]; };
|
|
149
|
+
...
|
|
150
|
+
dest = vec4(uintBitsToFloat(t0_buf[idx].value[(0 >> 2) + 0]),
|
|
151
|
+
uintBitsToFloat(t0_buf[idx].value[(0 >> 2) + 1]),
|
|
152
|
+
uintBitsToFloat(t0_buf[idx].value[(0 >> 2) + 2]),
|
|
153
|
+
uintBitsToFloat(t0_buf[idx].value[(0 >> 2) + 3]));
|
|
154
|
+
```
|
|
155
|
+
Verified against an actual generated fixture
|
|
156
|
+
(`../shaderdiscovery/artifacts/ab-shader-set/work/skinned_fxdirectionalv5/skinned_fxdirectionalv5.sm_hi.dxbc_29291f5662ed6781.vertex.es300.glsl:60-64`):
|
|
157
|
+
all four components of one row share the **same** byte offset (row 0 uses
|
|
158
|
+
`0`, row 1 uses `16`, row 2 uses `32` — i.e. the row's base byte offset, not
|
|
159
|
+
a per-component offset of `0/4/8/12`), differing only in the trailing
|
|
160
|
+
`+ 0/1/2/3` dword index, and **without** a `u` suffix on either the shift or
|
|
161
|
+
the addend. The missing `u` is not a formatting nit: in this corpus the
|
|
162
|
+
byte-offset operand is declared `SVT_INT` (not `SVT_UINT`), so
|
|
163
|
+
`srcOffFlag` resolves to `TO_FLAG_INTEGER`
|
|
164
|
+
(`toGLSLInstruction.cpp:1618-1621`), which suppresses the `u` suffix
|
|
165
|
+
entirely (see `printImmediate32`, `toGLSLOperand.cpp:371-387` vs. `388-395`).
|
|
166
|
+
This also matters functionally: `lowerStructuredBoneLoad`'s regex
|
|
167
|
+
(`packageTr2WebglEffect.js:875`) matches literal `(\d+)\s*>>\s*2\s*\)` with
|
|
168
|
+
no `u` tolerance, and its 4-component agreement check requires all four
|
|
169
|
+
loads to share one `byteOffset` — a per-component-varying offset of
|
|
170
|
+
`0/4/8/12` would both fail to match the regex *and* fail the "same
|
|
171
|
+
byteOffset" agreement check, silently no-opping the rewrite. The previous
|
|
172
|
+
worked example here was internally inconsistent with the very rewrite
|
|
173
|
+
contract it was illustrating.
|
|
174
|
+
2. A package-time rewrite pass (`scripts/packageTr2WebglEffect.js`,
|
|
175
|
+
functions `lowerWebgl2SkinningAbi` at lines 826-864 and
|
|
176
|
+
`lowerStructuredBoneLoad` at lines 873-902) runs over that generated GLSL text
|
|
177
|
+
and performs, **in this exact order**:
|
|
178
|
+
1. Strip the `#ifdef GL_ARB_shader_storage_buffer_object` /
|
|
179
|
+
`GL_ARB_shader_image_load_store` extension guard blocks (regexes at
|
|
180
|
+
`packageTr2WebglEffect.js:832-833`).
|
|
181
|
+
2. Strip the `struct t0_type { uint[1] value; };` declaration (regex at
|
|
182
|
+
`packageTr2WebglEffect.js:834`, matches only the 1-word/4-byte stride
|
|
183
|
+
shape).
|
|
184
|
+
3. Strip the `layout(std430, binding = 0) readonly buffer t0 { t0_type
|
|
185
|
+
t0_buf[]; };` declaration (regex at `packageTr2WebglEffect.js:835`).
|
|
186
|
+
4. Grow the vertex stage's `ConstantBuffer3` (`cb3`) declaration to
|
|
187
|
+
`vec4 data[max(existingSize, 200)]` (`packageTr2WebglEffect.js:836-839`) —
|
|
188
|
+
this is where `JointMat` lives at `cb3.data[26..199]` per the ccpwgl runtime
|
|
189
|
+
ABI (`cb3[26..199]`, 58 joints × 12 floats = 696 floats,
|
|
190
|
+
`AGENT-FINDINGS/decisions/016-cewg-skinning-abi-lowering-for-ccpwgl-2026-06-30.md`
|
|
191
|
+
and `015-joint-matrix-jointmat-findings-ccpwgl-runtime-truth.md`).
|
|
192
|
+
5. Convert `uvec4`/`ivec4` (or `uvec2/3`, `ivec2/3`) `in_BLENDINDICES<n>` vertex
|
|
193
|
+
inputs to plain `vec<N>` (regex at `packageTr2WebglEffect.js:840-843`) —
|
|
194
|
+
ccpwgl binds GR2 mesh blend indices as float attributes via
|
|
195
|
+
`vertexAttribPointer`, not `vertexAttribIPointer`
|
|
196
|
+
(`AGENT-FINDINGS/decisions/028-cewg-skinned-blend-index-abi-lowering.md`).
|
|
197
|
+
6. Strip the DX11 global bone-offset add HLSLcc emits when combining
|
|
198
|
+
`in_BLENDINDICES0` with a `cb3.data[26]` offset uniform (two regex forms at
|
|
199
|
+
`packageTr2WebglEffect.js:845-852`, covering both the scalar `int(...) +
|
|
200
|
+
floatBitsToInt(cb3.data[26].x)` shape and the vector `(i)uvec/ivec(...) +
|
|
201
|
+
floatBitsToInt(cb3.data[26].<swz>)` shape) — ccpwgl's `cb3.data[26]` slot is
|
|
202
|
+
reused for `JointMat`, not the native bone-ring-buffer offset, so this add
|
|
203
|
+
must be removed entirely rather than merely rewired.
|
|
204
|
+
7. Rewrite each 4-component `t0_buf[...]` row-load expression
|
|
205
|
+
(`vec4(t0_buf[idx].value[(byteOff>>2)+0], ...)`, all 4 components required,
|
|
206
|
+
`lowerStructuredBoneLoad`) into:
|
|
207
|
+
```glsl
|
|
208
|
+
cb3.data[26 + (<idx>) * 3 + <row>]
|
|
209
|
+
```
|
|
210
|
+
where `<row> = floor(byteOff / 16)` and must be in `{0,1,2}` (a `Float4x3`
|
|
211
|
+
bone matrix is 3 `vec4` rows); if any of the 4 component sub-expressions
|
|
212
|
+
disagree on `idx`/`byteOff`, or `row` falls outside `0..2`, or the swizzle
|
|
213
|
+
is anything but the identity `xyzw`/`.xyzw` is stripped when default,
|
|
214
|
+
**the rewrite silently no-ops and leaves the un-lowered `t0_buf` text in
|
|
215
|
+
place** (`packageTr2WebglEffect.js:886,890,895,898` all `return match`) —
|
|
216
|
+
this is a silent-failure edge case the implementing engineer must guard
|
|
217
|
+
against (add a diagnostic) rather than trust to fail loudly.
|
|
218
|
+
8. If any rewrite happened, inject a `// CEWG: BoneTransforms lowered to cb3
|
|
219
|
+
JointMat rows.` marker comment after `#version 300 es`
|
|
220
|
+
(`packageTr2WebglEffect.js:859-861`).
|
|
221
|
+
|
|
222
|
+
### GLSL lowering — C. `ld_structured` in pixel stage / non-skinning resources
|
|
223
|
+
The corpus also uses `ld_structured` on `t#` "packed tbuffer" resources unrelated
|
|
224
|
+
to skinning — e.g. `LightBuffer`/`LightIndexBuffer` reads in pixel shaders such as
|
|
225
|
+
`decalcylindricv5.sm_depth` (`AGENT-FINDINGS/decisions/005-structured-resource-only-opcodes-2026-06-26.md`).
|
|
226
|
+
**No `cb3`-style *functional* ABI rewrite exists for these** — they hit the same
|
|
227
|
+
SSBO-unavailability wall as section A. The emitter's default path lowers them to
|
|
228
|
+
pixel `usampler2D` data textures (see `DxbcGlslEmitter.js` `dcl_resource_structured`
|
|
229
|
+
pixel branch), which compiles but consumes a texture unit each; on real drivers
|
|
230
|
+
the `_depth` quad variants overflow `MAX_TEXTURE_IMAGE_UNITS`(16).
|
|
231
|
+
|
|
232
|
+
**Resolution (2026-07-08) — stub, not rewrite.** Since CEWG does not support this
|
|
233
|
+
tiled lighting, the packager can DROP it instead of lowering it. Run
|
|
234
|
+
`packageTr2WebglEffect.js --stub-light-resources`: it resolves the light resource
|
|
235
|
+
names (`LightBuffer`, `LightIndexBuffer`, `LightProfileArray`) to `t#` registers
|
|
236
|
+
from the Carbon `.sm` reflection (RDEF is stripped, so names live only there —
|
|
237
|
+
and the registers vary per permutation, so this is name-driven, not fixed to
|
|
238
|
+
sb11/sb12/s13) and passes them to `emitGlsl` as `stubResourceRegisters`. The
|
|
239
|
+
emitter then drops their decl+binding and lowers reads to `uintBitsToFloat(0u)`
|
|
240
|
+
(structured) / `vec4(0.0)` (sampled) — zeroing the per-tile light count makes the
|
|
241
|
+
light loop dead. The packager also strips those `resource` bindings from the
|
|
242
|
+
manifest JSON (`stripLightResourcesFromManifest`) so the CEWG runtime does not
|
|
243
|
+
synthesize a texture def (glType 0 → "Invalid shader texture definition") for the
|
|
244
|
+
now-undeclared light buffers. Opt-in, default off; every other package is
|
|
245
|
+
unchanged. A functional light constant-buffer path remains possible but was not
|
|
246
|
+
built.
|
|
247
|
+
|
|
248
|
+
Tested by `test/glsl-emitter.test.js` (synthetic pixel shaders with a structured
|
|
249
|
+
buffer / sampler2DArray: declared by default, dropped + no binding when the
|
|
250
|
+
register is in `stubResourceRegisters`, and only listed registers dropped) and
|
|
251
|
+
`test/stub-light-resources.test.js` (the packager's `resolveStubLightRegisters`
|
|
252
|
+
name→register resolution and `stripLightResourcesFromManifest` manifest filter,
|
|
253
|
+
in `scripts/stubLightResources.js`).
|
|
254
|
+
|
|
255
|
+
### Type rules
|
|
256
|
+
- Struct index operand: read as int/uint (both flags set in HLSLcc; pick uint by
|
|
257
|
+
default for ES 3.00).
|
|
258
|
+
- Byte-offset operand: uint unless the operand's own declared type is signed int.
|
|
259
|
+
- Result component type follows the *destination* register's inferred type
|
|
260
|
+
(float → `uintBitsToFloat`, int → `int(...)`, uint → passthrough), **not** the
|
|
261
|
+
source resource's declared return type — this is purely dest-driven, matching
|
|
262
|
+
the "everything is `float vec4`, bitcast at use" register model this project
|
|
263
|
+
already commits to.
|
|
264
|
+
- This is a data-movement instruction, not a comparison — it does not produce a
|
|
265
|
+
0xFFFFFFFF/0 mask.
|
|
266
|
+
|
|
267
|
+
### Helpers needed
|
|
268
|
+
- `structuredLoadComponent(bufName, structIndex, byteOffset, component, destType)`
|
|
269
|
+
— reference-only (HLSLcc SSBO shape), needed if the emitter ever targets a
|
|
270
|
+
non-WebGL2 backend or documents the pre-rewrite intermediate form.
|
|
271
|
+
- `lowerBoneTransformsToCb3` (package-time text pass; port of
|
|
272
|
+
`lowerWebgl2SkinningAbi` + `lowerStructuredBoneLoad`).
|
|
273
|
+
- `lowerBlendIndicesToFloatAttribute` (package-time text pass, part of the same
|
|
274
|
+
rewrite; port of the `in_BLENDINDICES` regex).
|
|
275
|
+
- `refuseNonSkinningStructuredLoad` (detection helper for section C).
|
|
276
|
+
|
|
277
|
+
### Edge cases
|
|
278
|
+
- NaN/inf: none introduced by the load itself; `uintBitsToFloat` is a pure
|
|
279
|
+
bit-reinterpret, so any NaN bit pattern already in the buffer round-trips as
|
|
280
|
+
NaN.
|
|
281
|
+
- The resource-operand swizzle indirection (`psSrc->aui32Swizzle[component]`)
|
|
282
|
+
means component `c` of the destination is not guaranteed to read structure
|
|
283
|
+
dword `c` — verify this against real corpus DXBC before assuming identity
|
|
284
|
+
swizzle always holds.
|
|
285
|
+
- The row/index-agreement check in `lowerStructuredBoneLoad` requires **all 4**
|
|
286
|
+
components to share the same `idx`/`byteOffset`; a destination write mask
|
|
287
|
+
narrower than `.xyzw` (e.g. `.xy`) will not match the 4-load regex and will
|
|
288
|
+
silently fail to rewrite — this is plausible for shaders that only need part of
|
|
289
|
+
a bone row and needs explicit test coverage.
|
|
290
|
+
- `bSaturate` on `ld_structured` is legal per the generic post-switch handling
|
|
291
|
+
but is not expected to appear in real bone/light-buffer loads; still must be
|
|
292
|
+
implemented for correctness if the corpus is ever re-scanned with `_sat`
|
|
293
|
+
detection.
|
|
294
|
+
|
|
295
|
+
### WebGL2 notes
|
|
296
|
+
- SSBOs (`buffer` blocks) do not exist in GLSL ES 3.00 at all; section A's
|
|
297
|
+
output is fundamentally uncompilable in WebGL2 and must never reach the
|
|
298
|
+
final package unless rewritten by section B.
|
|
299
|
+
- `layout(std430, binding=N)` is likewise unavailable in ES 3.00 (`std430` and UBO
|
|
300
|
+
binding indices exist, but SSBO binding does not).
|
|
301
|
+
|
|
302
|
+
### Confidence
|
|
303
|
+
**High** for the `BoneTransforms`/`cb3` path (validated end-to-end:
|
|
304
|
+
`336/336` and `240/240` WebGL2 program links per
|
|
305
|
+
`TRANSPILING-GAPS.md:60-63` and `016-cewg-skinning-abi-lowering-for-ccpwgl-2026-06-30.md`).
|
|
306
|
+
**Low** for non-skinning `ld_structured` in pixel stages — no validated WebGL2
|
|
307
|
+
lowering exists; treat as blocked pending a decision.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## `store_structured` (930 instances)
|
|
312
|
+
|
|
313
|
+
### Semantics
|
|
314
|
+
Writes one or more 32-bit components of a structured-buffer element addressed by
|
|
315
|
+
a structure index and byte offset, per D3D11 `store_structured` (the inverse of
|
|
316
|
+
`ld_structured`; only valid against a UAV, since D3D11 `structured buffer`
|
|
317
|
+
read-only resources cannot be written).
|
|
318
|
+
|
|
319
|
+
### GLSL lowering
|
|
320
|
+
`TranslateShaderStorageStore`, case `OPCODE_STORE_STRUCTURED`
|
|
321
|
+
(`vendor/HLSLcc/src/toGLSLInstruction.cpp:1500-1583`, dispatched at
|
|
322
|
+
`toGLSLInstruction.cpp:4348-4357`). Operands: `psDest=asOperands[0]` (the UAV
|
|
323
|
+
resource, carrying the write mask via `OPERAND_4_COMPONENT_MASK_MODE`),
|
|
324
|
+
`psDestAddr=asOperands[1]` (struct index), `psDestByteOff=asOperands[2]` (byte
|
|
325
|
+
offset), `psSrc=asOperands[3]` (value to store).
|
|
326
|
+
|
|
327
|
+
For each component present in `psDest->ui32CompMask`:
|
|
328
|
+
```glsl
|
|
329
|
+
<name>_buf[<structIndexExpr>].value[(<byteOffExpr> >> 2u) + <comp>u] = <uint-or-int-cast>(src.<swz-or-x>);
|
|
330
|
+
```
|
|
331
|
+
(`toGLSLInstruction.cpp:1534-1582`). `dstOffFlag` follows the same
|
|
332
|
+
unsigned-unless-signed-typed rule as `ld_structured`. The source cast (`srcFlag`)
|
|
333
|
+
is `TO_FLAG_UNSIGNED_INTEGER` by default, flipped to `TO_FLAG_INTEGER` only when
|
|
334
|
+
`DeclareRWStructuredBufferTemplateTypeAsInteger` reports the target buffer as a
|
|
335
|
+
single-`int`-typed `RWStructuredBuffer<int4>` (the "avoid calling the wrong
|
|
336
|
+
`AtomicMin` overload" special case, `toGLSLDeclaration.cpp:998-1025`) — otherwise
|
|
337
|
+
the destination array element type is always `uint` (`toGLSLInstruction.cpp:1569-1572`).
|
|
338
|
+
Source components are consumed left-to-right via an incrementing `srcComponent`
|
|
339
|
+
counter if the source operand has more than one swizzle element, else always
|
|
340
|
+
`.x` (`toGLSLInstruction.cpp:1575-1578`).
|
|
341
|
+
|
|
342
|
+
### Type rules
|
|
343
|
+
- Destination index/byte-offset: same int/uint rule as `ld_structured`.
|
|
344
|
+
- Source value: bitcast to uint (default) or int (special RWStructuredBuffer<int>
|
|
345
|
+
case) before storing — never stored as float, consistent with "backing array is
|
|
346
|
+
always uint".
|
|
347
|
+
|
|
348
|
+
### Helpers needed
|
|
349
|
+
- `structuredStoreComponent(bufName, structIndex, byteOffset, component, value,
|
|
350
|
+
srcType)` — reference-only; no WebGL2 target exists for this opcode (see below).
|
|
351
|
+
|
|
352
|
+
### Edge cases
|
|
353
|
+
- No destination register write, so `_sat` never applies (DXBC does not attach
|
|
354
|
+
`_sat` to store instructions).
|
|
355
|
+
- Per-component write masking must exactly follow `psDest->ui32CompMask`
|
|
356
|
+
(`OPERAND_4_COMPONENT_MASK_MODE`), not the source operand's own mask.
|
|
357
|
+
|
|
358
|
+
### WebGL2 notes
|
|
359
|
+
`store_structured` requires a writable UAV, which in turn requires an SSBO
|
|
360
|
+
(`buffer`, not `readonly buffer`) — completely unavailable in GLSL ES 3.00. No
|
|
361
|
+
package-time rewrite analogous to the `cb3` skinning path exists for writes
|
|
362
|
+
(there is no ccpwgl uniform target that plausibly receives a per-invocation
|
|
363
|
+
compute-style scatter write). **This opcode is out of scope for the WebGL2
|
|
364
|
+
emitter.** The 930 corpus instances should be treated as evidence this opcode
|
|
365
|
+
occurs in DX11 stages that are not shipped to the current WebGL2 vs/ps target
|
|
366
|
+
(the sampled corpus instance is `createhistograms.sm_depth`, tagged
|
|
367
|
+
`stageName: "geometry"` in `dx11-instruction-coverage.json` but much more
|
|
368
|
+
plausibly a mislabeled compute shader given the histogram-building workload
|
|
369
|
+
and its co-occurring `sync`/`dcl_thread_group`-shaped instruction in the same
|
|
370
|
+
file — see the `atomic_iadd` section for the one confirmed **non**-compute
|
|
371
|
+
counterexample in this family, `lensflareoccludert`, which is a pixel shader,
|
|
372
|
+
not compute); the emitter should detect and refuse rather than attempt
|
|
373
|
+
emission.
|
|
374
|
+
|
|
375
|
+
### Confidence
|
|
376
|
+
**Medium** on the HLSLcc reference lowering itself (directly read from source);
|
|
377
|
+
**high** on the WebGL2-scope conclusion (no counter-evidence of a vs/ps
|
|
378
|
+
`store_structured` shipping shader was found in the decision corpus, and the
|
|
379
|
+
project's own draft transpiler already special-cases the sibling UAV write
|
|
380
|
+
opcode `store_uav_typed` as a target blocker — see that section).
|
|
381
|
+
|
|
382
|
+
---
|
|
383
|
+
|
|
384
|
+
## `store_uav_typed` (642 instances)
|
|
385
|
+
|
|
386
|
+
### Semantics
|
|
387
|
+
Writes a full-precision (or format-converted) texel/element to a typed UAV
|
|
388
|
+
(`RWTexture*`/`RWBuffer`) at an integer address, per D3D11 `store_uav_typed`.
|
|
389
|
+
|
|
390
|
+
### GLSL lowering
|
|
391
|
+
Case `OPCODE_STORE_UAV_TYPED` (`vendor/HLSLcc/src/toGLSLInstruction.cpp:4359-4415`):
|
|
392
|
+
```glsl
|
|
393
|
+
imageStore(<uavName>, <addr-expr-by-dimension>, <value-cast-by-return-type>);
|
|
394
|
+
```
|
|
395
|
+
The address component mask and any `TO_AUTO_EXPAND_TO_VEC{2,3,4}` flag are chosen
|
|
396
|
+
from the UAV's reflected `REFLECT_RESOURCE_DIMENSION_*`
|
|
397
|
+
(`toGLSLInstruction.cpp:4382-4407`): 1D/Buffer → `.x` only; 2D/1DArray/2DMS →
|
|
398
|
+
`.xy` with `TO_AUTO_EXPAND_TO_VEC2`; 2DArray/3D/2DMSArray/Cube → `.xyz` with
|
|
399
|
+
`TO_AUTO_EXPAND_TO_VEC3`; CubeArray → `TO_AUTO_EXPAND_TO_VEC4`. The stored value
|
|
400
|
+
is translated with `ResourceReturnTypeToFlag(psRes->ui32ReturnType)` — i.e. cast
|
|
401
|
+
to match the UAV's declared return type (float/int/uint).
|
|
402
|
+
|
|
403
|
+
### Type rules
|
|
404
|
+
Value operand bitcast is driven entirely by the UAV's reflected return type
|
|
405
|
+
(`RETURN_TYPE_FLOAT`/`SINT`/`UINT`/`UNORM`/`SNORM`), not by any DXBC instruction
|
|
406
|
+
flag — this requires resource-binding reflection, which per
|
|
407
|
+
`CARBONENGINEJS-FORK.md:34-39` is frequently stripped in this project's shipped
|
|
408
|
+
DXBC and falls back to register-stable naming only (no return-type recovery
|
|
409
|
+
implied by that fallback).
|
|
410
|
+
|
|
411
|
+
### Helpers needed
|
|
412
|
+
None for the WebGL2 emitter proper — see WebGL2 notes. Reference-only helper:
|
|
413
|
+
`imageStoreTyped(uav, addr, value, returnType)`.
|
|
414
|
+
|
|
415
|
+
### Edge cases
|
|
416
|
+
- `imageStore` swizzle/expansion must match the UAV's declared dimensionality
|
|
417
|
+
exactly, or GLSL will reject a texel with the wrong component count.
|
|
418
|
+
- Missing `RDEF` reflection (this project's normal stripped-DXBC case) leaves the
|
|
419
|
+
return type unrecoverable, which independently blocks this opcode even before
|
|
420
|
+
the SSBO/image-type gap is considered.
|
|
421
|
+
|
|
422
|
+
### WebGL2 notes
|
|
423
|
+
`image2D`/`imageBuffer` UAV types and `imageStore` are GLSL ES 3.10+ built-ins,
|
|
424
|
+
not part of ES 3.00. **Fully out of scope for the WebGL2 emitter.** This matches
|
|
425
|
+
the project's own draft-transpiler decision, which already lists
|
|
426
|
+
`store_uav_typed` as a hard `TARGET_BLOCKER_OPCODES` entry
|
|
427
|
+
(`../shaderdiscovery/src/core/transpiler/gles/Dx11GlesDraftTranspiler.js:130`) and
|
|
428
|
+
the `TRANSPILING-GAPS.md:100-114` "UAV and atomic path... blocked for current
|
|
429
|
+
WebGL2 target" decision. The emitter must detect `dcl_unordered_access_view_*`
|
|
430
|
+
declarations plus this opcode and refuse the stage (or the whole effect) with an
|
|
431
|
+
explicit diagnostic, never attempt best-effort emission.
|
|
432
|
+
|
|
433
|
+
### Confidence
|
|
434
|
+
**High** — corroborated independently by HLSLcc source, the draft transpiler's
|
|
435
|
+
explicit blocker list, and the shaderdiscovery decision log.
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## `sync` (183 instances)
|
|
440
|
+
|
|
441
|
+
### Semantics
|
|
442
|
+
A compute-shader thread-group synchronization barrier. DXBC encodes which memory
|
|
443
|
+
domains/threads to synchronize via `ui32SyncFlags`: `SYNC_THREAD_GROUP_SHARED_MEMORY`,
|
|
444
|
+
`SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP`/`_GLOBAL`, and `SYNC_THREADS_IN_GROUP`.
|
|
445
|
+
It only has defined meaning inside a compute shader with a `dcl_thread_group` size.
|
|
446
|
+
|
|
447
|
+
### GLSL lowering
|
|
448
|
+
Case `OPCODE_SYNC` (`vendor/HLSLcc/src/toGLSLInstruction.cpp:3958-3984`):
|
|
449
|
+
```glsl
|
|
450
|
+
if (flags & SYNC_THREAD_GROUP_SHARED_MEMORY) memoryBarrierShared();
|
|
451
|
+
if (flags & (SYNC_UNORDERED_ACCESS_VIEW_MEMORY_GROUP|_GLOBAL)) memoryBarrier();
|
|
452
|
+
if (flags & SYNC_THREADS_IN_GROUP) barrier();
|
|
453
|
+
```
|
|
454
|
+
Each condition independently emits its statement (not mutually exclusive; a
|
|
455
|
+
single `sync` instruction can emit all three lines).
|
|
456
|
+
|
|
457
|
+
### Type rules
|
|
458
|
+
N/A — no operands, no data type.
|
|
459
|
+
|
|
460
|
+
### Helpers needed
|
|
461
|
+
None — this opcode has no GLSL ES 3.00 equivalent to helper-wrap; see WebGL2
|
|
462
|
+
notes.
|
|
463
|
+
|
|
464
|
+
### Edge cases
|
|
465
|
+
None beyond the flag decoding itself (a bitmask, not an enum — must check all
|
|
466
|
+
three bits independently, not `switch`/`else if`).
|
|
467
|
+
|
|
468
|
+
### WebGL2 notes
|
|
469
|
+
`barrier()`, `memoryBarrier()`, and `memoryBarrierShared()` are **compute-shader-
|
|
470
|
+
only** built-ins in GLSL ES (introduced with ES 3.10 compute shaders); they do
|
|
471
|
+
not exist in the ES 3.00 vertex/fragment built-in set at all, and vertex/fragment
|
|
472
|
+
shaders have no thread-group concept regardless of GLSL version. **Fully out of
|
|
473
|
+
scope for the WebGL2 emitter.** Detect `sync` (and its precondition,
|
|
474
|
+
`dcl_thread_group`) and refuse the stage.
|
|
475
|
+
|
|
476
|
+
### Confidence
|
|
477
|
+
**High** — the DXBC semantics and the compute-only nature of `barrier`/
|
|
478
|
+
`memoryBarrier` in GLSL ES are unambiguous.
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
482
|
+
## `ld_raw` (54 instances)
|
|
483
|
+
|
|
484
|
+
### Semantics
|
|
485
|
+
Reads one or more 32-bit components from a raw (`ByteAddressBuffer`) resource at
|
|
486
|
+
a byte offset, per D3D11 `ld_raw` — same addressing model as `ld_structured` but
|
|
487
|
+
without a structure index (flat byte-addressed array).
|
|
488
|
+
|
|
489
|
+
### GLSL lowering
|
|
490
|
+
Same function as `ld_structured`, `TranslateShaderStorageLoad`, case
|
|
491
|
+
`OPCODE_LD_RAW` (`vendor/HLSLcc/src/toGLSLInstruction.cpp:1602-1606`, dispatched
|
|
492
|
+
at `toGLSLInstruction.cpp:4416-4425`). Operands: `psDest=asOperands[0]`,
|
|
493
|
+
`psSrcByteOff=asOperands[1]`, `psSrc=asOperands[2]` — no `psSrcAddr`, so the
|
|
494
|
+
`TranslateShaderStorageLoad` body skips the `[<idx>].value` indirection
|
|
495
|
+
entirely (`toGLSLInstruction.cpp:1661-1666`, gated on `if (psSrcAddr)`), producing:
|
|
496
|
+
```glsl
|
|
497
|
+
<bitcast_open><name>_buf[(<byteOffExpr> >> 2u) + <comp>u]<bitcast_close>
|
|
498
|
+
```
|
|
499
|
+
against a flat `uint`/`int` array (`vendor/HLSLcc/src/toGLSLDeclaration.cpp:1078-1088`,
|
|
500
|
+
`isRaw` branch: `uint <name>_buf[];` or `int <name>_buf[];` chosen by
|
|
501
|
+
`HaveUnsignedTypes`), not a `_type` struct array.
|
|
502
|
+
|
|
503
|
+
### Type rules
|
|
504
|
+
Identical bitcast-by-destination-type rule as `ld_structured` (float →
|
|
505
|
+
`uintBitsToFloat`, int → `int(...)`, uint → passthrough).
|
|
506
|
+
|
|
507
|
+
### Helpers needed
|
|
508
|
+
- `rawLoadComponent(bufName, byteOffset, component, destType)` — reference-only;
|
|
509
|
+
see WebGL2 notes for scope.
|
|
510
|
+
|
|
511
|
+
### Edge cases
|
|
512
|
+
Same swizzle-indirection caveat as `ld_structured` (component addressing follows
|
|
513
|
+
the resource operand's own swizzle if present).
|
|
514
|
+
|
|
515
|
+
### WebGL2 notes
|
|
516
|
+
Same SSBO unavailability as `ld_structured` section A/C. No `cb3`-style rewrite
|
|
517
|
+
is known or defined for raw-buffer reads — the `BoneTransforms` rewrite is
|
|
518
|
+
specific to the structured-buffer `t0_buf[idx].value[...]` shape, not the flat
|
|
519
|
+
`t0_buf[...]` raw shape. **Out of scope for the WebGL2 emitter** unless/until a
|
|
520
|
+
specific raw-buffer resource is proven to need a package-time ABI rewrite
|
|
521
|
+
analogous to skinning.
|
|
522
|
+
|
|
523
|
+
The corpus table's "vs/ps" stage claim was overreach: the only sampled
|
|
524
|
+
instance in `dx11-instruction-coverage.json`'s `allOpcodeExamples` is
|
|
525
|
+
`graphics\effect.dx11\managed\space\specialfx\particles\gpu\emit.sm_depth`
|
|
526
|
+
tagged `stageName: "geometry"`, paired with the sibling `store_raw` opcode in
|
|
527
|
+
the exact same file/technique (also tagged `"geometry"`) — a GPU particle
|
|
528
|
+
emission pass, which is much more plausibly a compute-style workload than a
|
|
529
|
+
genuine vertex/pixel `ByteAddressBuffer` read. Do not assume `ld_raw` is
|
|
530
|
+
`vs/ps`-reachable without a concrete counter-example (unlike `atomic_iadd`,
|
|
531
|
+
which has one — see that section).
|
|
532
|
+
|
|
533
|
+
### Confidence
|
|
534
|
+
**Medium** — HLSLcc source lowering is directly read and clear, but no shipping
|
|
535
|
+
corpus evidence of `ld_raw` reaching a WebGL2-validated vs/ps program was found
|
|
536
|
+
(only 54 instances total, none flagged in the skinning/JointMat decision
|
|
537
|
+
trail); the sole sampled corpus example is paired with `store_raw` in a
|
|
538
|
+
likely-compute GPU-particle-emission shader, not a vs/ps stage.
|
|
539
|
+
|
|
540
|
+
---
|
|
541
|
+
|
|
542
|
+
## `store_raw` (54 instances)
|
|
543
|
+
|
|
544
|
+
### Semantics
|
|
545
|
+
Writes one or more 32-bit components to a raw UAV (`RWByteAddressBuffer`) at a
|
|
546
|
+
byte offset, per D3D11 `store_raw` — inverse of `ld_raw`.
|
|
547
|
+
|
|
548
|
+
### GLSL lowering
|
|
549
|
+
Same function as `store_structured`, `TranslateShaderStorageStore`, case
|
|
550
|
+
`OPCODE_STORE_RAW` (`vendor/HLSLcc/src/toGLSLInstruction.cpp:1519-1523`,
|
|
551
|
+
dispatched at `toGLSLInstruction.cpp:4338-4346`). Operands: `psDest=asOperands[0]`,
|
|
552
|
+
`psDestByteOff=asOperands[1]`, `psSrc=asOperands[2]` — no `psDestAddr`, so no
|
|
553
|
+
`[<idx>].value` indirection (`toGLSLInstruction.cpp:1546-1551`, gated on `if
|
|
554
|
+
(psDestAddr)`):
|
|
555
|
+
```glsl
|
|
556
|
+
<name>_buf[(<byteOffExpr> >> 2u) + <comp>u] = <uint-or-int-cast>(src.<swz-or-x>);
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
### Type rules
|
|
560
|
+
Same as `store_structured`: uint by default, int only for the special
|
|
561
|
+
single-int `RWStructuredBuffer<int4>`-shaped buffer detection (which does not
|
|
562
|
+
actually apply to raw buffers in practice, since that check is structured-buffer
|
|
563
|
+
specific, but the code path is shared).
|
|
564
|
+
|
|
565
|
+
### Helpers needed
|
|
566
|
+
- `rawStoreComponent(bufName, byteOffset, component, value, srcType)` —
|
|
567
|
+
reference-only.
|
|
568
|
+
|
|
569
|
+
### Edge cases
|
|
570
|
+
No destination register, so `_sat` never applies.
|
|
571
|
+
|
|
572
|
+
### WebGL2 notes
|
|
573
|
+
Requires a writable UAV/SSBO — unavailable in ES 3.00. **Out of scope for the
|
|
574
|
+
WebGL2 emitter**; treat identically to `store_structured` (detect and refuse).
|
|
575
|
+
|
|
576
|
+
### Confidence
|
|
577
|
+
**Medium** — same reasoning as `ld_raw`; low corpus volume (54) with no
|
|
578
|
+
known vs/ps shipping path.
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
## `atomic_iadd` (27) / `imm_atomic_iadd` (24) / `imm_atomic_exch` (9) / `atomic_umax` (6) / `atomic_umin` (3)
|
|
583
|
+
|
|
584
|
+
Grouped: all five are handled by the single `TranslateAtomicMemOp` function and
|
|
585
|
+
differ only in GLSL function name and whether a previous-value destination
|
|
586
|
+
exists.
|
|
587
|
+
|
|
588
|
+
### Semantics
|
|
589
|
+
- `atomic_iadd` / `imm_atomic_iadd`: atomically add a value to a UAV or
|
|
590
|
+
groupshared (TGSM) memory location; the `imm_` form additionally returns the
|
|
591
|
+
pre-add value into a destination register, the non-`imm_` form discards it.
|
|
592
|
+
- `imm_atomic_exch`: atomically replace the memory location's value and return
|
|
593
|
+
the previous value (exchange has no non-`imm_` counterpart in DXBC).
|
|
594
|
+
- `atomic_umax` / `atomic_umin`: atomically store `max`/`min` of the current
|
|
595
|
+
value and the source value (unsigned comparison), discarding the previous
|
|
596
|
+
value (no `imm_` variants observed in this corpus, though DXBC defines
|
|
597
|
+
`imm_atomic_umax`/`umin` too).
|
|
598
|
+
|
|
599
|
+
### GLSL lowering
|
|
600
|
+
`TranslateAtomicMemOp` (`vendor/HLSLcc/src/toGLSLInstruction.cpp:1685-2087`,
|
|
601
|
+
dispatched at `toGLSLInstruction.cpp:4428-4450`). Per-opcode operand layout and
|
|
602
|
+
GLSL function name selected at the top of the function
|
|
603
|
+
(`toGLSLInstruction.cpp:1700-1935`):
|
|
604
|
+
|
|
605
|
+
| Opcode | `func` | operands (dest addr order) |
|
|
606
|
+
|---|---|---|
|
|
607
|
+
| `imm_atomic_iadd` | `"Add"` | `[0]=previousValue, [1]=dest, [2]=destAddr, [3]=src` |
|
|
608
|
+
| `atomic_iadd` | `"Add"` | `[0]=dest, [1]=destAddr, [2]=src` (no previousValue) |
|
|
609
|
+
| `imm_atomic_exch` | `"Exchange"` | `[0]=previousValue, [1]=dest, [2]=destAddr, [3]=src` |
|
|
610
|
+
| `atomic_umin` | `"Min"` | `[0]=dest, [1]=destAddr, [2]=src` |
|
|
611
|
+
| `atomic_umax` | `"Max"` | `[0]=dest, [1]=destAddr, [2]=src` |
|
|
612
|
+
|
|
613
|
+
Resource-kind detection (`toGLSLInstruction.cpp:1968-2011`): if `dest` is not
|
|
614
|
+
`OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY`, look up its UAV binding.
|
|
615
|
+
`RTYPE_UAV_RWTYPED` → `isUint = (returnType == RETURN_TYPE_UINT)` and derive
|
|
616
|
+
`texDim` (1/2/3) from the UAV's resource dimension; `RTYPE_UAV_RWSTRUCTURED` →
|
|
617
|
+
`isUint=false, ui32DstDataTypeFlag |= TO_FLAG_INTEGER` only if
|
|
618
|
+
`DeclareRWStructuredBufferTemplateTypeAsInteger` says so; TGSM defaults to
|
|
619
|
+
`isUint=true, texDim=0`. Then:
|
|
620
|
+
```glsl
|
|
621
|
+
ui32DataTypeFlag = isUint ? (TO_FLAG_UNSIGNED_INTEGER|TO_AUTO_BITCAST_TO_UINT)
|
|
622
|
+
: (TO_FLAG_INTEGER|TO_AUTO_BITCAST_TO_INT);
|
|
623
|
+
```
|
|
624
|
+
(`toGLSLInstruction.cpp:2013-2016`). If `previousValue` exists, it's assigned via
|
|
625
|
+
`AddAssignToDest(previousValue, isUint?SVT_UINT:SVT_INT, 1, ...)` **before** the
|
|
626
|
+
atomic call text is emitted (`toGLSLInstruction.cpp:2018-2019`). Final emitted
|
|
627
|
+
shape (`toGLSLInstruction.cpp:2021-2086`):
|
|
628
|
+
- Typed-UAV (image) form (`texDim>0`):
|
|
629
|
+
```glsl
|
|
630
|
+
[prev =] imageAtomic<Func>(<uavName>, <addr>.<xy|xyz|x>, <src-cast>);
|
|
631
|
+
```
|
|
632
|
+
- Buffer/TGSM form (`texDim==0`):
|
|
633
|
+
```glsl
|
|
634
|
+
[prev =] atomic<Func>(<name>[_buf][<addr> >> 2u], <src-cast>);
|
|
635
|
+
```
|
|
636
|
+
where `<name>_buf[<addr>]` gains an extra `.value[<addrY> >> 2u]` indirection
|
|
637
|
+
if the destAddr operand carries **two** swizzle components (X and Y) — "structured
|
|
638
|
+
buf if we have both x & y swizzles" (`toGLSLInstruction.cpp:2055-2062`) — vs. a
|
|
639
|
+
raw buffer's single-component addressing.
|
|
640
|
+
- No trailing `;` is appended when `previousValue` is set (the assignment prologue
|
|
641
|
+
handles closing parens/semicolon via `AddAssignPrologue`); otherwise the line
|
|
642
|
+
is terminated with `;\n` directly (`toGLSLInstruction.cpp:2081-2086`).
|
|
643
|
+
|
|
644
|
+
### Type rules
|
|
645
|
+
- Both `compare`/`src` (when present) are cast via the same
|
|
646
|
+
`ui32DataTypeFlag` (`TO_AUTO_BITCAST_TO_UINT` or `_INT`), i.e. bitcast from the
|
|
647
|
+
underlying float-vec4 register storage to whichever integer type the target
|
|
648
|
+
memory location actually holds.
|
|
649
|
+
- `previousValue` destination type is `SVT_UINT` or `SVT_INT` matching `isUint`,
|
|
650
|
+
never float directly (though the register itself is stored as float and
|
|
651
|
+
bitcast at the destination-write site per this project's register model).
|
|
652
|
+
- These do **not** produce DXBC comparison masks; `atomic_umin`/`umax` compare
|
|
653
|
+
internally to select which value to store, but the DXBC/GLSL result is the
|
|
654
|
+
stored/previous *value*, not a boolean or 0xFFFFFFFF/0 mask.
|
|
655
|
+
|
|
656
|
+
### Helpers needed
|
|
657
|
+
None implementable for WebGL2 (see below). Reference-only helpers if ever
|
|
658
|
+
targeting ES 3.10+/desktop: `atomicUavOrTgsmOp(func, dest, addr, src,
|
|
659
|
+
[compare], [returnsPrevious])`.
|
|
660
|
+
|
|
661
|
+
### Edge cases
|
|
662
|
+
- `atomic_umin`/`atomic_umax` are unsigned-only per DXBC (`imin`/`imax` variants
|
|
663
|
+
exist separately for signed); do not conflate with `atomic_imin`/`imax`.
|
|
664
|
+
- The 1-vs-2-swizzle-component destAddr distinction (structured vs. raw
|
|
665
|
+
addressing within the same atomic path) must be preserved if this is ever
|
|
666
|
+
ported.
|
|
667
|
+
|
|
668
|
+
### WebGL2 notes
|
|
669
|
+
`atomicAdd`/`atomicMin`/`atomicMax`/`atomicExchange`/`atomicCompSwap` (buffer/
|
|
670
|
+
shared-memory atomics) and `imageAtomicAdd` etc. (image atomics) are GLSL ES
|
|
671
|
+
3.10+ compute-shader-only built-ins; none exist in ES 3.00 vertex/fragment
|
|
672
|
+
shaders, regardless of which D3D11 stage the source instruction came from.
|
|
673
|
+
**Fully out of scope for the WebGL2 emitter.** Detect any `atomic_*`/
|
|
674
|
+
`imm_atomic_*` opcode and refuse the stage.
|
|
675
|
+
|
|
676
|
+
Do **not** rely on "these only occur in compute shaders" as the reason for
|
|
677
|
+
skipping this check in the pixel-stage emitter: `dx11-instruction-coverage.json`
|
|
678
|
+
(`initialCandidateOpcodeExamples`) records a concrete `atomic_iadd` instance in
|
|
679
|
+
`graphics\effect.dx11\managed\space\specialfx\lensflares\lensflareoccludert.sm_depth`
|
|
680
|
+
tagged `stageIndex: 1` / `stageName: "pixel"` — an actual D3D11 pixel shader
|
|
681
|
+
(D3D11.1 permits UAV access from pixel shaders; a lens-flare occlusion query
|
|
682
|
+
written into a UAV counter from the pixel stage is a plausible, ordinary
|
|
683
|
+
technique, not a mislabeled compute pass). The other four sampled corpus
|
|
684
|
+
instances of this opcode group (`atomic_iadd` again in `createhistograms.sm_depth`,
|
|
685
|
+
`imm_atomic_iadd` in `clear.sm_depth`, `imm_atomic_exch`/`atomic_umax`/
|
|
686
|
+
`atomic_umin` in `computelightlists.sm_depth`) are all tagged `stageName:
|
|
687
|
+
"geometry"` by the same tool, but those files' names (histogram building,
|
|
688
|
+
particle-buffer clear, light-list culling) are classic GPGPU compute-shader
|
|
689
|
+
workloads, and the coverage tool has no `"compute"` stage label at all in its
|
|
690
|
+
vocabulary (only `vertex`/`pixel`/`geometry`/`hull`) — those four are much
|
|
691
|
+
better explained as compute shaders whose slot the tool mislabels than as
|
|
692
|
+
genuine geometry shaders (a real DX11 geometry shader cannot declare
|
|
693
|
+
`dcl_thread_group`/`sync`, which the *sibling* `createhistograms.sm_depth`
|
|
694
|
+
example for the `sync` opcode does, and DXBC does not permit that in a
|
|
695
|
+
geometry stage). The `lensflareoccludert` pixel-stage instance is not
|
|
696
|
+
explained away by that reasoning and must be treated as real: the emitter's
|
|
697
|
+
**ps-stage translation path itself** needs the detect-and-refuse check, not
|
|
698
|
+
just a pre-filter that assumes this opcode class never survives into a vs/ps
|
|
699
|
+
compile.
|
|
700
|
+
|
|
701
|
+
`TRANSPILING-GAPS.md:100-114` ("UAV and atomic path... blocked for current
|
|
702
|
+
WebGL2 target... `atomic_iadd`: 6... Affects the `lensflareoccludert` path" —
|
|
703
|
+
note that count was measured on a narrower earlier corpus slice than this
|
|
704
|
+
family's 450k-instruction sweep, which shows 27) already names
|
|
705
|
+
`lensflareoccludert` as the blocked case; it does not itself claim the
|
|
706
|
+
instruction is compute-only, and the per-instruction corpus scan confirms it
|
|
707
|
+
is not.
|
|
708
|
+
|
|
709
|
+
### Confidence
|
|
710
|
+
**High** for the DXBC/GLSL semantics (read directly from source) and for the
|
|
711
|
+
WebGL2-out-of-scope conclusion (ES 3.00 has no atomics in any stage, so the
|
|
712
|
+
`lensflareoccludert` pixel-shader counterexample does not change the outcome).
|
|
713
|
+
**Medium** on the blanket "compute-only" framing carried over from the
|
|
714
|
+
project's decision log — confirmed false for at least the `lensflareoccludert`
|
|
715
|
+
`atomic_iadd` instance, which is a pixel shader; the emitter must not assume
|
|
716
|
+
this opcode family is filtered out before reaching ps-stage translation.
|
|
717
|
+
|
|
718
|
+
---
|
|
719
|
+
|
|
720
|
+
## `ld_uav_typed` (18 instances)
|
|
721
|
+
|
|
722
|
+
### Semantics
|
|
723
|
+
Reads a texel/element from a typed UAV (`RWTexture*`/`RWBuffer`) at an integer
|
|
724
|
+
address, per D3D11 `ld_uav_typed` — the read counterpart of `store_uav_typed`.
|
|
725
|
+
|
|
726
|
+
### GLSL lowering
|
|
727
|
+
Case `OPCODE_LD_UAV_TYPED` (`vendor/HLSLcc/src/toGLSLInstruction.cpp:4266-4336`).
|
|
728
|
+
Operands: `psDest=asOperands[0]`, `psSrcAddr=asOperands[1]`,
|
|
729
|
+
`psSrc=asOperands[2]` (UAV resource). Address component mask derived from
|
|
730
|
+
`psInst->eResDim` the same way as `store_uav_typed` (1/2/3 components,
|
|
731
|
+
`toGLSLInstruction.cpp:4281-4300`). Source data type resolved from the UAV's
|
|
732
|
+
reflected return type (`RETURN_TYPE_FLOAT/SINT/UINT/SNORM/UNORM`,
|
|
733
|
+
`toGLSLInstruction.cpp:4302-4325`, with `UNORM`/`SNORM` both mapping to
|
|
734
|
+
`SVT_FLOAT`). Emitted form:
|
|
735
|
+
```glsl
|
|
736
|
+
dest.mask = imageLoad(<uavName>, <addr-by-dimension>)<swizzle-with-mask>;
|
|
737
|
+
```
|
|
738
|
+
using `AddAssignToDest`/`AddAssignPrologue` for the destination, and
|
|
739
|
+
`TranslateOperandSwizzleWithMask` to apply the resource operand's own swizzle to
|
|
740
|
+
the 4-component `imageLoad` result restricted to the destination write mask
|
|
741
|
+
(`toGLSLInstruction.cpp:4327-4335`).
|
|
742
|
+
|
|
743
|
+
### Type rules
|
|
744
|
+
Destination component type follows the UAV's reflected return type, not a fixed
|
|
745
|
+
uint-array convention (unlike `ld_structured`/`ld_raw`) — `imageLoad` always
|
|
746
|
+
returns a 4-component vector of the sampler/image's declared base type
|
|
747
|
+
(`ivec4`/`uvec4`/`vec4`), then swizzled down to the requested mask.
|
|
748
|
+
|
|
749
|
+
### Helpers needed
|
|
750
|
+
None for WebGL2 (see below). Reference-only: `imageLoadTyped(uav, addr,
|
|
751
|
+
returnType)`.
|
|
752
|
+
|
|
753
|
+
### Edge cases
|
|
754
|
+
Requires resource-binding reflection (return type, dimension) exactly like
|
|
755
|
+
`store_uav_typed` — doubly blocked when `RDEF` is stripped, independent of the
|
|
756
|
+
image-type gap below.
|
|
757
|
+
|
|
758
|
+
### WebGL2 notes
|
|
759
|
+
`imageLoad` and image sampler types (`image2D` etc.) are ES 3.10+-only.
|
|
760
|
+
**Fully out of scope for the WebGL2 emitter.** Matches the draft transpiler's
|
|
761
|
+
explicit blocker (`Dx11GlesDraftTranspiler.js:129`) and the
|
|
762
|
+
`TRANSPILING-GAPS.md` UAV decision. With only 18 corpus instances (vs.
|
|
763
|
+
`store_uav_typed`'s 642), this is very likely the read side of a small set of
|
|
764
|
+
compute/UAV effects rather than any vs/ps-reachable code path — but the
|
|
765
|
+
concrete sampled instance (`dx11-instruction-coverage.json`, `allOpcodeExamples`)
|
|
766
|
+
is `graphics\effect.dx11\managed\space\postprocess\measureexposure.sm_depth`
|
|
767
|
+
(a tone-mapping average-luminance compute pass), **not** `lensflareoccludert`.
|
|
768
|
+
`lensflareoccludert` is confirmed by `TRANSPILING-GAPS.md:100-114` to carry
|
|
769
|
+
`dcl_unordered_access_view_typed`/`atomic_iadd` (and per this family's own
|
|
770
|
+
corpus scan, `atomic_iadd` there is a **pixel**-stage instance — see that
|
|
771
|
+
section); do not conflate the two effects or assume `ld_uav_typed`'s
|
|
772
|
+
compute-only reasoning transfers to `atomic_iadd`.
|
|
773
|
+
|
|
774
|
+
### Confidence
|
|
775
|
+
**High** — same corroboration as `store_uav_typed`, corrected to cite the
|
|
776
|
+
right sampled effect (`measureexposure.sm_depth`, not `lensflareoccludert`).
|
|
777
|
+
|
|
778
|
+
---
|
|
779
|
+
|
|
780
|
+
## `bufinfo` (0 instances — specified for completeness only)
|
|
781
|
+
|
|
782
|
+
### Semantics
|
|
783
|
+
Returns the element count of a structured/raw/typed buffer resource, per D3D11
|
|
784
|
+
`bufinfo` (used for bounds-checking dynamic buffer accesses).
|
|
785
|
+
|
|
786
|
+
### GLSL lowering
|
|
787
|
+
Case `OPCODE_BUFINFO` (`vendor/HLSLcc/src/toGLSLInstruction.cpp:4753-4766`):
|
|
788
|
+
```glsl
|
|
789
|
+
dest = <ctor>(<resourceName>_buf.length());
|
|
790
|
+
```
|
|
791
|
+
via `AddAssignToDest(dest, SVT_INT, 1, ...)` then
|
|
792
|
+
`<resourceName>_buf.length()` then `AddAssignPrologue`.
|
|
793
|
+
|
|
794
|
+
### Type rules
|
|
795
|
+
Result is always `SVT_INT` (a signed count), regardless of the buffer's element
|
|
796
|
+
type.
|
|
797
|
+
|
|
798
|
+
### Helpers needed
|
|
799
|
+
None — zero corpus instances; no helper is justified without evidence of use.
|
|
800
|
+
|
|
801
|
+
### Edge cases
|
|
802
|
+
N/A — not observed in this corpus.
|
|
803
|
+
|
|
804
|
+
### WebGL2 notes
|
|
805
|
+
`.length()` on a GLSL array returns a compile-time constant for fixed-size
|
|
806
|
+
arrays (legal in ES 3.00) but is a **run-time** query only for SSBO
|
|
807
|
+
runtime-sized arrays (`buffer T { ... x[]; }`), which do not exist in ES 3.00.
|
|
808
|
+
Since this opcode's only real use (bounds-checking a structured/raw buffer) is
|
|
809
|
+
tied to the same SSBO-only resource kinds as `ld_structured`/`ld_raw`, it would
|
|
810
|
+
be out of scope for the same reason if it appeared. Zero corpus instances means
|
|
811
|
+
no immediate action item, but the emitter should still recognize and refuse the
|
|
812
|
+
opcode defensively rather than silently mis-translate.
|
|
813
|
+
|
|
814
|
+
### Confidence
|
|
815
|
+
**Low** — zero real-world evidence in this corpus; semantics and lowering are
|
|
816
|
+
read directly from HLSLcc source but entirely unvalidated against any actual
|
|
817
|
+
shader.
|
|
818
|
+
|
|
819
|
+
---
|
|
820
|
+
|
|
821
|
+
## Helpers summary
|
|
822
|
+
|
|
823
|
+
Helpers the memory-structured family needs the emitter to provide (grouped by
|
|
824
|
+
whether they produce runnable WebGL2 output or are reference/detection-only):
|
|
825
|
+
|
|
826
|
+
**Shipping (WebGL2-runnable) helpers:**
|
|
827
|
+
1. `lowerBoneTransformsToCb3` — package-time text-rewrite pass that removes the
|
|
828
|
+
HLSLcc `t0` SSBO declaration, grows `cb3.data[]` to at least 200 `vec4`s,
|
|
829
|
+
strips the native bone-ring-buffer offset add, and rewrites each 4-component
|
|
830
|
+
`t0_buf[idx].value[...]` row load to `cb3.data[26 + idx*3 + row]` (optionally
|
|
831
|
+
swizzled). Port of `lowerWebgl2SkinningAbi` +
|
|
832
|
+
`lowerStructuredBoneLoad` in `scripts/packageTr2WebglEffect.js:826-902`.
|
|
833
|
+
2. `lowerBlendIndicesToFloatAttribute` — package-time rewrite of
|
|
834
|
+
`uvec4`/`ivec4`/etc. `in_BLENDINDICES<n>` vertex inputs to `vec<N>`, part of
|
|
835
|
+
the same pass (`packageTr2WebglEffect.js:840-843`).
|
|
836
|
+
|
|
837
|
+
**Reference-only helpers** (mirror HLSLcc's non-WebGL2 SSBO/UAV/atomic/compute
|
|
838
|
+
lowering, useful for documentation, debugging, and any future non-WebGL2
|
|
839
|
+
backend, but must never be emitted as final WebGL2 output):
|
|
840
|
+
3. `structuredLoadComponent(bufName, structIndex, byteOffset, component, destType)`
|
|
841
|
+
4. `structuredStoreComponent(bufName, structIndex, byteOffset, component, value, srcType)`
|
|
842
|
+
5. `rawLoadComponent(bufName, byteOffset, component, destType)`
|
|
843
|
+
6. `rawStoreComponent(bufName, byteOffset, component, value, srcType)`
|
|
844
|
+
7. `imageLoadTyped(uav, addr, returnType)`
|
|
845
|
+
8. `imageStoreTyped(uav, addr, value, returnType)`
|
|
846
|
+
9. `atomicUavOrTgsmOp(func, dest, addr, src, compare?, returnsPrevious?)`
|
|
847
|
+
|
|
848
|
+
**Detection/refusal helpers** (must run before emission; there is no GLSL ES
|
|
849
|
+
3.00 lowering to fall back to):
|
|
850
|
+
10. `refuseComputeOnlyOpcode(opcodeName)` — for `sync`, `store_structured`
|
|
851
|
+
(non-skinning), `store_raw`, `store_uav_typed`, `ld_uav_typed`,
|
|
852
|
+
`atomic_iadd`, `imm_atomic_iadd`, `imm_atomic_exch`, `atomic_umax`,
|
|
853
|
+
`atomic_umin`, and `bufinfo` should it ever appear.
|
|
854
|
+
11. `refuseNonSkinningStructuredLoad(resourceName)` — for `ld_structured` /
|
|
855
|
+
`ld_raw` uses that are not the vertex-stage `BoneTransforms` skinning
|
|
856
|
+
pattern (e.g. `LightBuffer`/`LightIndexBuffer` pixel-stage reads).
|
|
857
|
+
|
|
858
|
+
---
|
|
859
|
+
|
|
860
|
+
*Sources consulted: `vendor/HLSLcc/src/toGLSLInstruction.cpp`,
|
|
861
|
+
`toGLSLOperand.cpp`, `toGLSLDeclaration.cpp`, `HLSLccToolkit.cpp`,
|
|
862
|
+
`internal_includes/languages.h`; `vendor/HLSLcc/CARBONENGINEJS-FORK.md`;
|
|
863
|
+
`../shaderdiscovery/TRANSPILING-GAPS.md`; `../shaderdiscovery/AGENT-FINDINGS/decisions/005-`,
|
|
864
|
+
`016-`, `028-cewg-*`, `014-`/`015-`/`016-`/`017-joint-matrix-*`;
|
|
865
|
+
`../shaderdiscovery/src/core/transpiler/gles/Dx11GlesDraftTranspiler.js` (hints
|
|
866
|
+
only); `scripts/packageTr2WebglEffect.js`;
|
|
867
|
+
`../shaderdiscovery/artifacts/dx11-instruction-coverage.json` (per-instruction
|
|
868
|
+
stage ground truth, used to correct several "compute-only" stage-reality
|
|
869
|
+
claims); `../shaderdiscovery/artifacts/ab-shader-set/work/skinned_fxdirectionalv5/*.es300.glsl`
|
|
870
|
+
(actual generated fixture, used to correct the `ld_structured` cb3 worked
|
|
871
|
+
example).*
|