@carbonenginejs/runtime-resource 0.10.0 → 0.11.0
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/format/effect/effectPermutationGraph.js +257 -0
- package/dist/format/effect/effectPermutationGraph.js.map +1 -0
- package/dist/format/effect/effectReflectionPackage.js +636 -0
- package/dist/format/effect/effectReflectionPackage.js.map +1 -0
- package/dist/format/effect/sha256.js +114 -0
- package/dist/format/effect/sha256.js.map +1 -0
- package/dist/formats/dxbc/CjsDxbcFormat.js +142 -0
- package/dist/formats/dxbc/CjsDxbcFormat.js.map +1 -0
- package/dist/formats/dxbc/core/DxbcReader.js +266 -0
- package/dist/formats/dxbc/core/DxbcReader.js.map +1 -0
- package/dist/formats/dxbc/core/container.js +169 -0
- package/dist/formats/dxbc/core/container.js.map +1 -0
- package/dist/formats/dxbc/core/decoder.js +789 -0
- package/dist/formats/dxbc/core/decoder.js.map +1 -0
- package/dist/formats/dxbc/core/errors.js +19 -0
- package/dist/formats/dxbc/core/errors.js.map +1 -0
- package/dist/formats/dxbc/core/helpers.js +220 -0
- package/dist/formats/dxbc/core/helpers.js.map +1 -0
- package/dist/formats/dxbc/core/opcodes.js +45 -0
- package/dist/formats/dxbc/core/opcodes.js.map +1 -0
- package/dist/formats/dxbc/core/program.js +91 -0
- package/dist/formats/dxbc/core/program.js.map +1 -0
- package/dist/formats/dxbc/core/signature.js +172 -0
- package/dist/formats/dxbc/core/signature.js.map +1 -0
- package/dist/formats/dxbc/index.js +2 -0
- package/dist/formats/dxbc/index.js.map +1 -0
- package/dist/formats/hlsl/CjsHlslFormat.js +254 -0
- package/dist/formats/hlsl/CjsHlslFormat.js.map +1 -0
- package/dist/formats/hlsl/core/HlslBinaryUtils.js +15 -0
- package/dist/formats/hlsl/core/HlslBinaryUtils.js.map +1 -0
- package/dist/formats/hlsl/core/HlslEffectReadError.js +19 -0
- package/dist/formats/hlsl/core/HlslEffectReadError.js.map +1 -0
- package/dist/formats/hlsl/core/HlslEffectStateManager.js +130 -0
- package/dist/formats/hlsl/core/HlslEffectStateManager.js.map +1 -0
- package/dist/formats/hlsl/core/HlslReader.js +266 -0
- package/dist/formats/hlsl/core/HlslReader.js.map +1 -0
- package/dist/formats/hlsl/core/HlslRenderStateSetup.js +37 -0
- package/dist/formats/hlsl/core/HlslRenderStateSetup.js.map +1 -0
- package/dist/formats/hlsl/core/HlslResourceSetDescription.js +94 -0
- package/dist/formats/hlsl/core/HlslResourceSetDescription.js.map +1 -0
- package/dist/formats/hlsl/core/HlslShaderBytecode.js +44 -0
- package/dist/formats/hlsl/core/HlslShaderBytecode.js.map +1 -0
- package/dist/formats/hlsl/core/analysis.js +51 -0
- package/dist/formats/hlsl/core/analysis.js.map +1 -0
- package/dist/formats/hlsl/core/helpers.js +270 -0
- package/dist/formats/hlsl/core/helpers.js.map +1 -0
- package/dist/formats/hlsl/core/json.js +284 -0
- package/dist/formats/hlsl/core/json.js.map +1 -0
- package/dist/formats/hlsl/core/metadata.js +327 -0
- package/dist/formats/hlsl/core/metadata.js.map +1 -0
- package/dist/formats/hlsl/core/portableReflection.js +848 -0
- package/dist/formats/hlsl/core/portableReflection.js.map +1 -0
- package/dist/formats/hlsl/core/render-states.js +280 -0
- package/dist/formats/hlsl/core/render-states.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/HlslRenderContextEnum.js +43 -0
- package/dist/formats/hlsl/core/tr2/HlslRenderContextEnum.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/resources/HlslEffectRes.js +294 -0
- package/dist/formats/hlsl/core/tr2/resources/HlslEffectRes.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/resources/HlslShaderPermutation.js +33 -0
- package/dist/formats/hlsl/core/tr2/resources/HlslShaderPermutation.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectBindingManifest.js +416 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectBindingManifest.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectConstant.js +40 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectConstant.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectDescription.js +742 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectDescription.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectLibrary.js +52 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectLibrary.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectParameterAnnotation.js +38 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectParameterAnnotation.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectResource.js +50 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectResource.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectStageInput.js +86 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectStageInput.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectTechnique.js +31 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslEffectTechnique.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslPass.js +42 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslPass.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslSamplerDescription.js +55 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslSamplerDescription.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslSamplerSetup.js +29 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslSamplerSetup.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslShader.js +220 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslShader.js.map +1 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslShaderOption.js +30 -0
- package/dist/formats/hlsl/core/tr2/shader/HlslShaderOption.js.map +1 -0
- package/dist/formats/hlsl/index.js +2 -0
- package/dist/formats/hlsl/index.js.map +1 -0
- package/dist/formats/hlsl/portable.js +2 -0
- package/dist/formats/hlsl/portable.js.map +1 -0
- package/dist/formats/index.js +4 -0
- package/dist/formats/index.js.map +1 -1
- package/dist/formats/webgl/CjsWebglFormat.js +221 -0
- package/dist/formats/webgl/CjsWebglFormat.js.map +1 -0
- package/dist/formats/webgl/core/cewg/CewgPackage.js +339 -0
- package/dist/formats/webgl/core/cewg/CewgPackage.js.map +1 -0
- package/dist/formats/webgl/core/cewg/CewgPackageBuilder.js +104 -0
- package/dist/formats/webgl/core/cewg/CewgPackageBuilder.js.map +1 -0
- package/dist/formats/webgl/core/cewg/binary.js +101 -0
- package/dist/formats/webgl/core/cewg/binary.js.map +1 -0
- package/dist/formats/webgl/core/cewgCompleteness.js +81 -0
- package/dist/formats/webgl/core/cewgCompleteness.js.map +1 -0
- package/dist/formats/webgl/core/effectPackage.js +789 -0
- package/dist/formats/webgl/core/effectPackage.js.map +1 -0
- package/dist/formats/webgl/core/effectPackageValidation.js +331 -0
- package/dist/formats/webgl/core/effectPackageValidation.js.map +1 -0
- package/dist/formats/webgl/core/errors.js +27 -0
- package/dist/formats/webgl/core/errors.js.map +1 -0
- package/dist/formats/webgl/core/glsl/DxbcGlslEmitter.js +2678 -0
- package/dist/formats/webgl/core/glsl/DxbcGlslEmitter.js.map +1 -0
- package/dist/formats/webgl/core/glsl/DxbcGlslHelpers.js +89 -0
- package/dist/formats/webgl/core/glsl/DxbcGlslHelpers.js.map +1 -0
- package/dist/formats/webgl/core/glsl/DxbcGlslOperandFormatter.js +428 -0
- package/dist/formats/webgl/core/glsl/DxbcGlslOperandFormatter.js.map +1 -0
- package/dist/formats/webgl/core/helpers.js +306 -0
- package/dist/formats/webgl/core/helpers.js.map +1 -0
- package/dist/formats/webgl/index.js +2 -0
- package/dist/formats/webgl/index.js.map +1 -0
- package/dist/formats/webgpu/CjsWebgpuFormat.js +376 -0
- package/dist/formats/webgpu/CjsWebgpuFormat.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackage.js +415 -0
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackage.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackageBuilder.js +100 -0
- package/dist/formats/webgpu/core/cewgpu/CewgpuPackageBuilder.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/binary.js +93 -0
- package/dist/formats/webgpu/core/cewgpu/binary.js.map +1 -0
- package/dist/formats/webgpu/core/cewgpu/tags.js +17 -0
- package/dist/formats/webgpu/core/cewgpu/tags.js.map +1 -0
- package/dist/formats/webgpu/core/effectAnalysis.js +82 -0
- package/dist/formats/webgpu/core/effectAnalysis.js.map +1 -0
- package/dist/formats/webgpu/core/effectBackendBodySet.js +305 -0
- package/dist/formats/webgpu/core/effectBackendBodySet.js.map +1 -0
- package/dist/formats/webgpu/core/effectPackageValidation.js +1078 -0
- package/dist/formats/webgpu/core/effectPackageValidation.js.map +1 -0
- package/dist/formats/webgpu/core/errors.js +20 -0
- package/dist/formats/webgpu/core/errors.js.map +1 -0
- package/dist/formats/webgpu/core/helpers.js +448 -0
- package/dist/formats/webgpu/core/helpers.js.map +1 -0
- package/dist/formats/webgpu/core/ir/analyzeRegisterValues.js +223 -0
- package/dist/formats/webgpu/core/ir/analyzeRegisterValues.js.map +1 -0
- package/dist/formats/webgpu/core/ir/buildControlFlow.js +220 -0
- package/dist/formats/webgpu/core/ir/buildControlFlow.js.map +1 -0
- package/dist/formats/webgpu/core/ir/indexableTemps.js +137 -0
- package/dist/formats/webgpu/core/ir/indexableTemps.js.map +1 -0
- package/dist/formats/webgpu/core/ir/inferValueTypes.js +454 -0
- package/dist/formats/webgpu/core/ir/inferValueTypes.js.map +1 -0
- package/dist/formats/webgpu/core/ir/lowerDxbcToIr.js +494 -0
- package/dist/formats/webgpu/core/ir/lowerDxbcToIr.js.map +1 -0
- package/dist/formats/webgpu/core/ir/resolveRegisterFlow.js +177 -0
- package/dist/formats/webgpu/core/ir/resolveRegisterFlow.js.map +1 -0
- package/dist/formats/webgpu/core/ir/sourceLanes.js +61 -0
- package/dist/formats/webgpu/core/ir/sourceLanes.js.map +1 -0
- package/dist/formats/webgpu/core/packageEffect.js +300 -0
- package/dist/formats/webgpu/core/packageEffect.js.map +1 -0
- package/dist/formats/webgpu/core/packageEffectSelection.js +164 -0
- package/dist/formats/webgpu/core/packageEffectSelection.js.map +1 -0
- package/dist/formats/webgpu/core/packageMetadata.js +8 -0
- package/dist/formats/webgpu/core/packageMetadata.js.map +1 -0
- package/dist/formats/webgpu/core/schema.js +4 -0
- package/dist/formats/webgpu/core/schema.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js +275 -0
- package/dist/formats/webgpu/core/wgsl/buildResourceTransformPlan.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/buildWgslBindingPlan.js +182 -0
- package/dist/formats/webgpu/core/wgsl/buildWgslBindingPlan.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/buildWgslSet.js +324 -0
- package/dist/formats/webgpu/core/wgsl/buildWgslSet.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/emitWgsl.js +356 -0
- package/dist/formats/webgpu/core/wgsl/emitWgsl.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/hoistEscapingValues.js +77 -0
- package/dist/formats/webgpu/core/wgsl/hoistEscapingValues.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerBindingLayout.js +451 -0
- package/dist/formats/webgpu/core/wgsl/lowerBindingLayout.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerComputeProgram.js +754 -0
- package/dist/formats/webgpu/core/wgsl/lowerComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerCreateHistogramsComputeProgram.js +457 -0
- package/dist/formats/webgpu/core/wgsl/lowerCreateHistogramsComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerFragmentProgram.js +1572 -0
- package/dist/formats/webgpu/core/wgsl/lowerFragmentProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerMergeHistogramsComputeProgram.js +659 -0
- package/dist/formats/webgpu/core/wgsl/lowerMergeHistogramsComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerParticleClearComputePrograms.js +734 -0
- package/dist/formats/webgpu/core/wgsl/lowerParticleClearComputePrograms.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerParticleEmitComputeProgram.js +583 -0
- package/dist/formats/webgpu/core/wgsl/lowerParticleEmitComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerSkinVerticesComputeProgram.js +621 -0
- package/dist/formats/webgpu/core/wgsl/lowerSkinVerticesComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerSortComputeProgram.js +824 -0
- package/dist/formats/webgpu/core/wgsl/lowerSortComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerSortInnerComputeProgram.js +697 -0
- package/dist/formats/webgpu/core/wgsl/lowerSortInnerComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerSortStepComputeProgram.js +559 -0
- package/dist/formats/webgpu/core/wgsl/lowerSortStepComputeProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/lowerVertexProgram.js +1328 -0
- package/dist/formats/webgpu/core/wgsl/lowerVertexProgram.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/particleEmitSemanticDigest.js +110 -0
- package/dist/formats/webgpu/core/wgsl/particleEmitSemanticDigest.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/precisionControls.js +55 -0
- package/dist/formats/webgpu/core/wgsl/precisionControls.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/selectionPlans.js +758 -0
- package/dist/formats/webgpu/core/wgsl/selectionPlans.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/uniformity.js +78 -0
- package/dist/formats/webgpu/core/wgsl/uniformity.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/validateExactComputeIr.js +196 -0
- package/dist/formats/webgpu/core/wgsl/validateExactComputeIr.js.map +1 -0
- package/dist/formats/webgpu/core/wgsl/validateHandleOperand.js +37 -0
- package/dist/formats/webgpu/core/wgsl/validateHandleOperand.js.map +1 -0
- package/dist/formats/webgpu/index.js +2 -0
- package/dist/formats/webgpu/index.js.map +1 -0
- package/dist/resource/shader/Tr2EffectRes.js +159 -150
- package/dist/resource/shader/Tr2EffectRes.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialArea.js +23 -28
- package/dist/resource/shader/Tr2MaterialArea.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialMesh.js +21 -27
- package/dist/resource/shader/Tr2MaterialMesh.js.map +1 -1
- package/dist/resource/shader/Tr2MaterialRes.js +24 -29
- package/dist/resource/shader/Tr2MaterialRes.js.map +1 -1
- package/dist/resource/shader/Tr2Shader.js +45 -39
- package/dist/resource/shader/Tr2Shader.js.map +1 -1
- package/dist/resource/shader/Tr2ShaderPermutation.js +30 -32
- package/dist/resource/shader/Tr2ShaderPermutation.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectConstant.js +113 -78
- package/dist/resource/shader/reflection/Tr2EffectConstant.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectDefine.js +17 -23
- package/dist/resource/shader/reflection/Tr2EffectDefine.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectDescription.js +23 -29
- package/dist/resource/shader/reflection/Tr2EffectDescription.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectLibrary.js +44 -40
- package/dist/resource/shader/reflection/Tr2EffectLibrary.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectParameterAnnotation.js +82 -86
- package/dist/resource/shader/reflection/Tr2EffectParameterAnnotation.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectResource.js +55 -61
- package/dist/resource/shader/reflection/Tr2EffectResource.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectStageInput.js +49 -45
- package/dist/resource/shader/reflection/Tr2EffectStageInput.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2EffectTechnique.js +25 -30
- package/dist/resource/shader/reflection/Tr2EffectTechnique.js.map +1 -1
- package/dist/resource/shader/reflection/Tr2Pass.js +30 -32
- package/dist/resource/shader/reflection/Tr2Pass.js.map +1 -1
- package/dist/resource/shader/sampler/Tr2SamplerSetup.js +21 -26
- package/dist/resource/shader/sampler/Tr2SamplerSetup.js.map +1 -1
- package/docs/formats/README.md +4 -0
- package/docs/formats/provenance.md +11 -3
- package/docs/reference/classes/formats.md +440 -0
- package/format-notices/dxbc/LICENSE +21 -0
- package/format-notices/dxbc/NOTICE +20 -0
- package/format-notices/hlsl/LICENSE +21 -0
- package/format-notices/hlsl/NOTICE +25 -0
- package/format-notices/webgl/LICENSE +21 -0
- package/format-notices/webgl/NOTICE +35 -0
- package/format-notices/webgpu/LICENSE +21 -0
- package/format-notices/webgpu/NOTICE +31 -0
- package/package.json +6 -1
- package/dist/resource/shader/portableValidation.js +0 -461
- package/dist/resource/shader/portableValidation.js.map +0 -1
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { fixedSourceLanes } from './sourceLanes.js';
|
|
2
|
+
import { validateIndexableTempOperand } from './indexableTemps.js';
|
|
3
|
+
|
|
4
|
+
const COMPONENTS = ["x", "y", "z", "w"];
|
|
5
|
+
const REGISTER_FILES = new Set(["temp", "input", "output", "indexable_temp", "input_primitive_id", "output_depth", "output_coverage", "input_control_point", "output_control_point", "input_patch_constant", "input_domain_point", "output_control_point_id", "input_fork_instance_id", "input_join_instance_id", "input_thread_id", "input_thread_group_id", "input_thread_id_in_group", "input_coverage_mask", "input_thread_id_in_group_flattened", "input_gs_instance_id", "output_depth_greater_equal", "output_depth_less_equal"]);
|
|
6
|
+
const WRITABLE_FILES = new Set(["temp", "output", "indexable_temp", "output_depth", "output_coverage", "output_control_point", "output_depth_greater_equal", "output_depth_less_equal"]);
|
|
7
|
+
const NO_DESTINATION = new Set(["break", "breakc", "call", "callc", "case", "continue", "continuec", "cut", "default", "discard", "else", "emit", "emit_then_cut", "endif", "endloop", "endswitch", "if", "label", "loop", "nop", "ret", "retc", "switch", "sync", "store_uav_typed", "store_raw", "store_structured", "atomic_and", "atomic_or", "atomic_xor", "atomic_cmp_store", "atomic_iadd", "atomic_imax", "atomic_imin", "atomic_umax", "atomic_umin"]);
|
|
8
|
+
const DUAL_DESTINATION = new Set(["sincos", "imul", "umul", "udiv", "swapc"]);
|
|
9
|
+
const FULL_SOURCE_LANES = new Set(["ld", "ld_ms", "resinfo"]);
|
|
10
|
+
function operandComponents(operand, destination = false, activeComponents = null) {
|
|
11
|
+
if (destination) {
|
|
12
|
+
if (operand.mask) return COMPONENTS.filter(component => operand.mask.includes(component));
|
|
13
|
+
if (operand.componentCount === 1) return ["x"];
|
|
14
|
+
return COMPONENTS.slice();
|
|
15
|
+
}
|
|
16
|
+
if (operand.swizzle) {
|
|
17
|
+
return activeComponents ? activeComponents.map(component => operand.swizzle[COMPONENTS.indexOf(component)]) : Array.from(operand.swizzle);
|
|
18
|
+
}
|
|
19
|
+
if (operand.selected) return activeComponents ? activeComponents.map(() => operand.selected) : [operand.selected];
|
|
20
|
+
if (operand.mask) return COMPONENTS.filter(component => operand.mask.includes(component));
|
|
21
|
+
if (operand.componentCount === 1) return ["x"];
|
|
22
|
+
return activeComponents ? activeComponents.slice() : COMPONENTS.slice();
|
|
23
|
+
}
|
|
24
|
+
function registerKey(program, operand, role) {
|
|
25
|
+
if (!REGISTER_FILES.has(operand.typeName)) return null;
|
|
26
|
+
if (operand.typeName === "indexable_temp") {
|
|
27
|
+
return validateIndexableTempOperand(program, operand, role)?.key || null;
|
|
28
|
+
}
|
|
29
|
+
const indices = (operand.indices || []).map(index => {
|
|
30
|
+
const immediate = index.values?.join(":") || "";
|
|
31
|
+
return index.relative ? `${immediate}+relative` : immediate;
|
|
32
|
+
});
|
|
33
|
+
return `${operand.typeName}[${indices.join(",")}]`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Classifies decoded instruction operands as register sources or destinations.
|
|
38
|
+
*
|
|
39
|
+
* @param {object} instruction Decoded instruction.
|
|
40
|
+
* @returns {Array<{operand: object, role: string}>} Ordered operand roles.
|
|
41
|
+
*/
|
|
42
|
+
function operandRoles(instruction) {
|
|
43
|
+
const operands = instruction.operands || [];
|
|
44
|
+
if (NO_DESTINATION.has(instruction.opcodeName)) {
|
|
45
|
+
return operands.map(operand => ({
|
|
46
|
+
operand,
|
|
47
|
+
role: "source"
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
if (DUAL_DESTINATION.has(instruction.opcodeName)) {
|
|
51
|
+
return operands.map((operand, index) => ({
|
|
52
|
+
operand,
|
|
53
|
+
role: index < 2 ? "destination" : "source"
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
return operands.map((operand, index) => ({
|
|
57
|
+
operand,
|
|
58
|
+
role: index === 0 && WRITABLE_FILES.has(operand.typeName) ? "destination" : "source"
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
function valueRef(value, component) {
|
|
62
|
+
return {
|
|
63
|
+
valueId: value.id,
|
|
64
|
+
component
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function ensureComponent(state, values, register, component, blockId) {
|
|
68
|
+
let components = state.get(register);
|
|
69
|
+
if (!components) {
|
|
70
|
+
components = new Map();
|
|
71
|
+
state.set(register, components);
|
|
72
|
+
}
|
|
73
|
+
if (!components.has(component)) {
|
|
74
|
+
const value = {
|
|
75
|
+
kind: "register-value",
|
|
76
|
+
id: `value${values.length}`,
|
|
77
|
+
origin: "block-input",
|
|
78
|
+
blockId,
|
|
79
|
+
instructionIndex: null,
|
|
80
|
+
register,
|
|
81
|
+
writeMask: component,
|
|
82
|
+
previous: null
|
|
83
|
+
};
|
|
84
|
+
values.push(value);
|
|
85
|
+
components.set(component, valueRef(value, component));
|
|
86
|
+
}
|
|
87
|
+
return components.get(component);
|
|
88
|
+
}
|
|
89
|
+
function analyzeBlock(program, block, values) {
|
|
90
|
+
const state = new Map();
|
|
91
|
+
const inputIds = new Set();
|
|
92
|
+
for (const instructionIndex of block.instructionIndices) {
|
|
93
|
+
const instruction = program.instructions[instructionIndex];
|
|
94
|
+
const roles = operandRoles(instruction);
|
|
95
|
+
const destinationComponents = Array.from(new Set(roles.filter(entry => entry.role === "destination" && entry.operand.typeName !== "null").flatMap(entry => operandComponents(entry.operand, true))));
|
|
96
|
+
const activeSourceComponents = destinationComponents.length && !FULL_SOURCE_LANES.has(instruction.opcodeName) ? destinationComponents : null;
|
|
97
|
+
const reads = [];
|
|
98
|
+
const writes = [];
|
|
99
|
+
for (let operandIndex = 0; operandIndex < roles.length; operandIndex += 1) {
|
|
100
|
+
const {
|
|
101
|
+
operand,
|
|
102
|
+
role
|
|
103
|
+
} = roles[operandIndex];
|
|
104
|
+
if (role !== "source") continue;
|
|
105
|
+
const register = registerKey(program, operand, "source");
|
|
106
|
+
if (!register) continue;
|
|
107
|
+
const components = operandComponents(operand, false, fixedSourceLanes(instruction, operandIndex, program) || activeSourceComponents);
|
|
108
|
+
const refs = components.map(component => ensureComponent(state, values, register, component, block.id));
|
|
109
|
+
for (const ref of refs) {
|
|
110
|
+
const value = values.find(entry => entry.id === ref.valueId);
|
|
111
|
+
if (value?.origin === "block-input") inputIds.add(value.id);
|
|
112
|
+
}
|
|
113
|
+
reads.push({
|
|
114
|
+
kind: "register-read",
|
|
115
|
+
operandIndex,
|
|
116
|
+
register,
|
|
117
|
+
components,
|
|
118
|
+
refs
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
for (let operandIndex = 0; operandIndex < roles.length; operandIndex += 1) {
|
|
122
|
+
const {
|
|
123
|
+
operand
|
|
124
|
+
} = roles[operandIndex];
|
|
125
|
+
const indices = operand.indices || [];
|
|
126
|
+
for (let dimension = 0; dimension < indices.length; dimension += 1) {
|
|
127
|
+
const relative = indices[dimension].relative;
|
|
128
|
+
if (!relative) continue;
|
|
129
|
+
const register = registerKey(program, relative, "source");
|
|
130
|
+
if (!register) throw new Error("Shader IR relative index uses an unsupported register file");
|
|
131
|
+
const components = operandComponents(relative, false);
|
|
132
|
+
if (components.length !== 1) throw new Error("Shader IR relative index requires one scalar component");
|
|
133
|
+
const refs = components.map(component => ensureComponent(state, values, register, component, block.id));
|
|
134
|
+
for (const ref of refs) {
|
|
135
|
+
const value = values.find(entry => entry.id === ref.valueId);
|
|
136
|
+
if (value?.origin === "block-input") inputIds.add(value.id);
|
|
137
|
+
}
|
|
138
|
+
reads.push({
|
|
139
|
+
kind: "index-read",
|
|
140
|
+
operandIndex,
|
|
141
|
+
dimension,
|
|
142
|
+
register,
|
|
143
|
+
components,
|
|
144
|
+
refs
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
for (let operandIndex = 0; operandIndex < roles.length; operandIndex += 1) {
|
|
149
|
+
const {
|
|
150
|
+
operand,
|
|
151
|
+
role
|
|
152
|
+
} = roles[operandIndex];
|
|
153
|
+
if (role !== "destination" || operand.typeName === "null") continue;
|
|
154
|
+
const register = registerKey(program, operand, "destination");
|
|
155
|
+
if (!register) continue;
|
|
156
|
+
const mask = operandComponents(operand, true);
|
|
157
|
+
const previous = {};
|
|
158
|
+
for (const component of COMPONENTS) {
|
|
159
|
+
if (!mask.includes(component)) {
|
|
160
|
+
previous[component] = ensureComponent(state, values, register, component, block.id);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const value = {
|
|
164
|
+
kind: "register-value",
|
|
165
|
+
id: `value${values.length}`,
|
|
166
|
+
origin: "instruction-write",
|
|
167
|
+
blockId: block.id,
|
|
168
|
+
instructionIndex,
|
|
169
|
+
register,
|
|
170
|
+
writeMask: mask.join(""),
|
|
171
|
+
previous: Object.keys(previous).length ? previous : null
|
|
172
|
+
};
|
|
173
|
+
values.push(value);
|
|
174
|
+
let components = state.get(register);
|
|
175
|
+
if (!components) {
|
|
176
|
+
components = new Map();
|
|
177
|
+
state.set(register, components);
|
|
178
|
+
}
|
|
179
|
+
for (const component of mask) components.set(component, valueRef(value, component));
|
|
180
|
+
const result = {};
|
|
181
|
+
for (const component of COMPONENTS) {
|
|
182
|
+
result[component] = components.get(component) || ensureComponent(state, values, register, component, block.id);
|
|
183
|
+
}
|
|
184
|
+
writes.push({
|
|
185
|
+
kind: "register-write",
|
|
186
|
+
operandIndex,
|
|
187
|
+
register,
|
|
188
|
+
mask: mask.join(""),
|
|
189
|
+
valueId: value.id,
|
|
190
|
+
previous: value.previous,
|
|
191
|
+
result
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
instruction.dataflow = {
|
|
195
|
+
reads,
|
|
196
|
+
writes
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
block.inputValueIds = Array.from(inputIds);
|
|
200
|
+
block.outputValues = Array.from(state.entries()).flatMap(([register, components]) => Array.from(components.entries()).map(([component, ref]) => ({
|
|
201
|
+
register,
|
|
202
|
+
component,
|
|
203
|
+
ref
|
|
204
|
+
}))).sort((a, b) => a.register.localeCompare(b.register) || a.component.localeCompare(b.component));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Adds block-local register versions, masked-write reconstruction records,
|
|
209
|
+
* and deterministic block-exit state. A later pass resolves the conservative
|
|
210
|
+
* block inputs through CFG predecessors.
|
|
211
|
+
*
|
|
212
|
+
* @param {object} program Mutable shader IR under construction.
|
|
213
|
+
* @returns {object} The same program.
|
|
214
|
+
*/
|
|
215
|
+
function analyzeRegisterValues(program) {
|
|
216
|
+
const values = [];
|
|
217
|
+
for (const block of program.blocks) analyzeBlock(program, block, values);
|
|
218
|
+
program.values = values;
|
|
219
|
+
return program;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export { analyzeRegisterValues, operandRoles };
|
|
223
|
+
//# sourceMappingURL=analyzeRegisterValues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyzeRegisterValues.js","sources":["../../../../../../src/formats/webgpu/core/ir/analyzeRegisterValues.js"],"sourcesContent":["import { fixedSourceLanes } from \"./sourceLanes.js\";\nimport { validateIndexableTempOperand } from \"./indexableTemps.js\";\n\nconst COMPONENTS = [ \"x\", \"y\", \"z\", \"w\" ];\n\nconst REGISTER_FILES = new Set([\n \"temp\", \"input\", \"output\", \"indexable_temp\", \"input_primitive_id\",\n \"output_depth\", \"output_coverage\", \"input_control_point\",\n \"output_control_point\", \"input_patch_constant\", \"input_domain_point\",\n \"output_control_point_id\", \"input_fork_instance_id\", \"input_join_instance_id\",\n \"input_thread_id\", \"input_thread_group_id\", \"input_thread_id_in_group\",\n \"input_coverage_mask\", \"input_thread_id_in_group_flattened\",\n \"input_gs_instance_id\", \"output_depth_greater_equal\", \"output_depth_less_equal\"\n]);\n\nconst WRITABLE_FILES = new Set([\n \"temp\", \"output\", \"indexable_temp\", \"output_depth\", \"output_coverage\",\n \"output_control_point\", \"output_depth_greater_equal\", \"output_depth_less_equal\"\n]);\n\nconst NO_DESTINATION = new Set([\n \"break\", \"breakc\", \"call\", \"callc\", \"case\", \"continue\", \"continuec\",\n \"cut\", \"default\", \"discard\", \"else\", \"emit\", \"emit_then_cut\", \"endif\",\n \"endloop\", \"endswitch\", \"if\", \"label\", \"loop\", \"nop\", \"ret\", \"retc\",\n \"switch\", \"sync\", \"store_uav_typed\", \"store_raw\", \"store_structured\",\n \"atomic_and\", \"atomic_or\", \"atomic_xor\", \"atomic_cmp_store\", \"atomic_iadd\",\n \"atomic_imax\", \"atomic_imin\", \"atomic_umax\", \"atomic_umin\"\n]);\n\nconst DUAL_DESTINATION = new Set([ \"sincos\", \"imul\", \"umul\", \"udiv\", \"swapc\" ]);\nconst FULL_SOURCE_LANES = new Set([\n \"ld\", \"ld_ms\", \"resinfo\"\n]);\n\nfunction operandComponents(operand, destination = false, activeComponents = null)\n{\n if (destination)\n {\n if (operand.mask) return COMPONENTS.filter((component) => operand.mask.includes(component));\n if (operand.componentCount === 1) return [ \"x\" ];\n return COMPONENTS.slice();\n }\n if (operand.swizzle)\n {\n return activeComponents\n ? activeComponents.map((component) => operand.swizzle[COMPONENTS.indexOf(component)])\n : Array.from(operand.swizzle);\n }\n if (operand.selected) return activeComponents ? activeComponents.map(() => operand.selected) : [ operand.selected ];\n if (operand.mask) return COMPONENTS.filter((component) => operand.mask.includes(component));\n if (operand.componentCount === 1) return [ \"x\" ];\n return activeComponents ? activeComponents.slice() : COMPONENTS.slice();\n}\n\nfunction registerKey(program, operand, role)\n{\n if (!REGISTER_FILES.has(operand.typeName)) return null;\n if (operand.typeName === \"indexable_temp\")\n {\n return validateIndexableTempOperand(program, operand, role)?.key || null;\n }\n const indices = (operand.indices || []).map((index) =>\n {\n const immediate = index.values?.join(\":\") || \"\";\n return index.relative ? `${immediate}+relative` : immediate;\n });\n return `${operand.typeName}[${indices.join(\",\")}]`;\n}\n\n/**\n * Classifies decoded instruction operands as register sources or destinations.\n *\n * @param {object} instruction Decoded instruction.\n * @returns {Array<{operand: object, role: string}>} Ordered operand roles.\n */\nexport function operandRoles(instruction)\n{\n const operands = instruction.operands || [];\n if (NO_DESTINATION.has(instruction.opcodeName))\n {\n return operands.map((operand) => ({ operand, role: \"source\" }));\n }\n if (DUAL_DESTINATION.has(instruction.opcodeName))\n {\n return operands.map((operand, index) => ({ operand, role: index < 2 ? \"destination\" : \"source\" }));\n }\n return operands.map((operand, index) => ({\n operand,\n role: index === 0 && WRITABLE_FILES.has(operand.typeName) ? \"destination\" : \"source\"\n }));\n}\n\nfunction valueRef(value, component)\n{\n return { valueId: value.id, component };\n}\n\nfunction ensureComponent(state, values, register, component, blockId)\n{\n let components = state.get(register);\n if (!components)\n {\n components = new Map();\n state.set(register, components);\n }\n if (!components.has(component))\n {\n const value = {\n kind: \"register-value\",\n id: `value${values.length}`,\n origin: \"block-input\",\n blockId,\n instructionIndex: null,\n register,\n writeMask: component,\n previous: null\n };\n values.push(value);\n components.set(component, valueRef(value, component));\n }\n return components.get(component);\n}\n\nfunction analyzeBlock(program, block, values)\n{\n const state = new Map();\n const inputIds = new Set();\n for (const instructionIndex of block.instructionIndices)\n {\n const instruction = program.instructions[instructionIndex];\n const roles = operandRoles(instruction);\n const destinationComponents = Array.from(new Set(roles\n .filter((entry) => entry.role === \"destination\" && entry.operand.typeName !== \"null\")\n .flatMap((entry) => operandComponents(entry.operand, true))));\n const activeSourceComponents = destinationComponents.length && !FULL_SOURCE_LANES.has(instruction.opcodeName)\n ? destinationComponents\n : null;\n const reads = [];\n const writes = [];\n\n for (let operandIndex = 0; operandIndex < roles.length; operandIndex += 1)\n {\n const { operand, role } = roles[operandIndex];\n if (role !== \"source\") continue;\n const register = registerKey(program, operand, \"source\");\n if (!register) continue;\n const components = operandComponents(\n operand,\n false,\n fixedSourceLanes(instruction, operandIndex, program) || activeSourceComponents);\n const refs = components.map((component) => ensureComponent(state, values, register, component, block.id));\n for (const ref of refs)\n {\n const value = values.find((entry) => entry.id === ref.valueId);\n if (value?.origin === \"block-input\") inputIds.add(value.id);\n }\n reads.push({ kind: \"register-read\", operandIndex, register, components, refs });\n }\n\n for (let operandIndex = 0; operandIndex < roles.length; operandIndex += 1)\n {\n const { operand } = roles[operandIndex];\n const indices = operand.indices || [];\n for (let dimension = 0; dimension < indices.length; dimension += 1)\n {\n const relative = indices[dimension].relative;\n if (!relative) continue;\n const register = registerKey(program, relative, \"source\");\n if (!register) throw new Error(\"Shader IR relative index uses an unsupported register file\");\n const components = operandComponents(relative, false);\n if (components.length !== 1) throw new Error(\"Shader IR relative index requires one scalar component\");\n const refs = components.map((component) => ensureComponent(state, values, register, component, block.id));\n for (const ref of refs)\n {\n const value = values.find((entry) => entry.id === ref.valueId);\n if (value?.origin === \"block-input\") inputIds.add(value.id);\n }\n reads.push({ kind: \"index-read\", operandIndex, dimension, register, components, refs });\n }\n }\n\n for (let operandIndex = 0; operandIndex < roles.length; operandIndex += 1)\n {\n const { operand, role } = roles[operandIndex];\n if (role !== \"destination\" || operand.typeName === \"null\") continue;\n const register = registerKey(program, operand, \"destination\");\n if (!register) continue;\n const mask = operandComponents(operand, true);\n const previous = {};\n for (const component of COMPONENTS)\n {\n if (!mask.includes(component))\n {\n previous[component] = ensureComponent(state, values, register, component, block.id);\n }\n }\n const value = {\n kind: \"register-value\",\n id: `value${values.length}`,\n origin: \"instruction-write\",\n blockId: block.id,\n instructionIndex,\n register,\n writeMask: mask.join(\"\"),\n previous: Object.keys(previous).length ? previous : null\n };\n values.push(value);\n let components = state.get(register);\n if (!components)\n {\n components = new Map();\n state.set(register, components);\n }\n for (const component of mask) components.set(component, valueRef(value, component));\n const result = {};\n for (const component of COMPONENTS)\n {\n result[component] = components.get(component) || ensureComponent(state, values, register, component, block.id);\n }\n writes.push({\n kind: \"register-write\",\n operandIndex,\n register,\n mask: mask.join(\"\"),\n valueId: value.id,\n previous: value.previous,\n result\n });\n }\n instruction.dataflow = { reads, writes };\n }\n block.inputValueIds = Array.from(inputIds);\n block.outputValues = Array.from(state.entries())\n .flatMap(([ register, components ]) => Array.from(components.entries())\n .map(([ component, ref ]) => ({ register, component, ref })))\n .sort((a, b) => a.register.localeCompare(b.register) || a.component.localeCompare(b.component));\n}\n\n/**\n * Adds block-local register versions, masked-write reconstruction records,\n * and deterministic block-exit state. A later pass resolves the conservative\n * block inputs through CFG predecessors.\n *\n * @param {object} program Mutable shader IR under construction.\n * @returns {object} The same program.\n */\nexport function analyzeRegisterValues(program)\n{\n const values = [];\n for (const block of program.blocks) analyzeBlock(program, block, values);\n program.values = values;\n return program;\n}\n"],"names":["COMPONENTS","REGISTER_FILES","Set","WRITABLE_FILES","NO_DESTINATION","DUAL_DESTINATION","FULL_SOURCE_LANES","operandComponents","operand","destination","activeComponents","mask","filter","component","includes","componentCount","slice","swizzle","map","indexOf","Array","from","selected","registerKey","program","role","has","typeName","validateIndexableTempOperand","key","indices","index","immediate","values","join","relative","operandRoles","instruction","operands","opcodeName","valueRef","value","valueId","id","ensureComponent","state","register","blockId","components","get","Map","set","kind","length","origin","instructionIndex","writeMask","previous","push","analyzeBlock","block","inputIds","instructionIndices","instructions","roles","destinationComponents","entry","flatMap","activeSourceComponents","reads","writes","operandIndex","fixedSourceLanes","refs","ref","find","add","dimension","Error","Object","keys","result","dataflow","inputValueIds","outputValues","entries","sort","a","b","localeCompare","analyzeRegisterValues","blocks"],"mappings":"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"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
const CONDITIONAL_EXITS = new Set(["retc", "discard"]);
|
|
2
|
+
const TERMINAL_EXITS = new Set(["ret", "abort"]);
|
|
3
|
+
const UNSUPPORTED_FLOW = new Set(["call", "callc", "label", "interface_call"]);
|
|
4
|
+
function collectRegions(instructions) {
|
|
5
|
+
const regions = [];
|
|
6
|
+
const stack = [];
|
|
7
|
+
const requireTop = (kind, opcode, index) => {
|
|
8
|
+
const region = stack.at(-1);
|
|
9
|
+
if (!region || region.kind !== kind) {
|
|
10
|
+
throw new Error(`Shader IR has mismatched ${opcode} at instruction ${index}`);
|
|
11
|
+
}
|
|
12
|
+
return region;
|
|
13
|
+
};
|
|
14
|
+
for (const instruction of instructions) {
|
|
15
|
+
const index = instruction.index;
|
|
16
|
+
switch (instruction.opcodeName) {
|
|
17
|
+
case "if":
|
|
18
|
+
stack.push({
|
|
19
|
+
kind: "selection",
|
|
20
|
+
startInstruction: index,
|
|
21
|
+
elseInstruction: null
|
|
22
|
+
});
|
|
23
|
+
break;
|
|
24
|
+
case "else":
|
|
25
|
+
{
|
|
26
|
+
const region = requireTop("selection", "else", index);
|
|
27
|
+
if (region.elseInstruction !== null) throw new Error(`Shader IR has duplicate else at instruction ${index}`);
|
|
28
|
+
region.elseInstruction = index;
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
case "endif":
|
|
32
|
+
{
|
|
33
|
+
const region = requireTop("selection", "endif", index);
|
|
34
|
+
stack.pop();
|
|
35
|
+
region.endInstruction = index;
|
|
36
|
+
regions.push(region);
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
case "loop":
|
|
40
|
+
stack.push({
|
|
41
|
+
kind: "loop",
|
|
42
|
+
startInstruction: index
|
|
43
|
+
});
|
|
44
|
+
break;
|
|
45
|
+
case "endloop":
|
|
46
|
+
{
|
|
47
|
+
const region = requireTop("loop", "endloop", index);
|
|
48
|
+
stack.pop();
|
|
49
|
+
region.endInstruction = index;
|
|
50
|
+
regions.push(region);
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
case "switch":
|
|
54
|
+
stack.push({
|
|
55
|
+
kind: "switch",
|
|
56
|
+
startInstruction: index,
|
|
57
|
+
caseInstructions: [],
|
|
58
|
+
defaultInstruction: null
|
|
59
|
+
});
|
|
60
|
+
break;
|
|
61
|
+
case "case":
|
|
62
|
+
{
|
|
63
|
+
const region = requireTop("switch", "case", index);
|
|
64
|
+
region.caseInstructions.push(index);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
case "default":
|
|
68
|
+
{
|
|
69
|
+
const region = requireTop("switch", "default", index);
|
|
70
|
+
if (region.defaultInstruction !== null) throw new Error(`Shader IR has duplicate default at instruction ${index}`);
|
|
71
|
+
region.defaultInstruction = index;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
case "endswitch":
|
|
75
|
+
{
|
|
76
|
+
const region = requireTop("switch", "endswitch", index);
|
|
77
|
+
stack.pop();
|
|
78
|
+
region.endInstruction = index;
|
|
79
|
+
regions.push(region);
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (stack.length) {
|
|
85
|
+
throw new Error("Shader IR contains an unterminated structured control-flow region");
|
|
86
|
+
}
|
|
87
|
+
return regions.sort((a, b) => a.startInstruction - b.startInstruction);
|
|
88
|
+
}
|
|
89
|
+
function containingRegion(regions, instructionIndex, kinds) {
|
|
90
|
+
return regions.filter(region => kinds.has(region.kind) && region.startInstruction < instructionIndex && instructionIndex < region.endInstruction).sort((a, b) => b.startInstruction - a.startInstruction)[0] || null;
|
|
91
|
+
}
|
|
92
|
+
function addEdge(from, to, kind) {
|
|
93
|
+
if (!to) return;
|
|
94
|
+
if (!from.successors.some(edge => edge.blockId === to.id && edge.kind === kind)) {
|
|
95
|
+
from.successors.push({
|
|
96
|
+
blockId: to.id,
|
|
97
|
+
kind
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Adds structured CFG edges without attempting register SSA construction.
|
|
104
|
+
* Join blocks receive merge-site metadata consumed by the later SSA pass.
|
|
105
|
+
*
|
|
106
|
+
* @param {object} program Mutable shader IR under construction.
|
|
107
|
+
* @returns {object} The same program.
|
|
108
|
+
*/
|
|
109
|
+
function buildControlFlow(program) {
|
|
110
|
+
const {
|
|
111
|
+
blocks,
|
|
112
|
+
instructions
|
|
113
|
+
} = program;
|
|
114
|
+
const unsupported = instructions.find(instruction => UNSUPPORTED_FLOW.has(instruction.opcodeName));
|
|
115
|
+
if (unsupported) {
|
|
116
|
+
throw new Error(`Shader IR does not yet support ${unsupported.opcodeName} control flow at instruction ${unsupported.index}`);
|
|
117
|
+
}
|
|
118
|
+
const regions = collectRegions(instructions);
|
|
119
|
+
const blockAtInstruction = new Map();
|
|
120
|
+
const blockById = new Map(blocks.map(block => [block.id, block]));
|
|
121
|
+
for (const block of blocks) {
|
|
122
|
+
block.successors = [];
|
|
123
|
+
block.predecessors = [];
|
|
124
|
+
block.exits = [];
|
|
125
|
+
block.mergeSite = null;
|
|
126
|
+
for (const index of block.instructionIndices) blockAtInstruction.set(index, block);
|
|
127
|
+
}
|
|
128
|
+
const blockAfterInstruction = index => blockAtInstruction.get(index + 1) || null;
|
|
129
|
+
const regionStartingAt = new Map(regions.map(region => [region.startInstruction, region]));
|
|
130
|
+
const elseRegion = new Map(regions.filter(region => region.kind === "selection" && region.elseInstruction !== null).map(region => [region.elseInstruction, region]));
|
|
131
|
+
for (const block of blocks) {
|
|
132
|
+
const last = instructions[block.endInstruction];
|
|
133
|
+
const next = blocks[block.index + 1] || null;
|
|
134
|
+
const opcode = last.opcodeName;
|
|
135
|
+
const region = regionStartingAt.get(last.index);
|
|
136
|
+
if (opcode === "if") {
|
|
137
|
+
const trueTarget = region.elseInstruction === next?.startInstruction ? blockAtInstruction.get(region.endInstruction) : next;
|
|
138
|
+
addEdge(block, trueTarget, "selection-true");
|
|
139
|
+
const falseInstruction = region.elseInstruction ?? region.endInstruction;
|
|
140
|
+
addEdge(block, blockAtInstruction.get(falseInstruction), "selection-false");
|
|
141
|
+
} else if (opcode === "switch") {
|
|
142
|
+
for (const caseInstruction of region.caseInstructions) {
|
|
143
|
+
addEdge(block, blockAtInstruction.get(caseInstruction), "switch-case");
|
|
144
|
+
}
|
|
145
|
+
const fallback = region.defaultInstruction ?? region.endInstruction;
|
|
146
|
+
addEdge(block, blockAtInstruction.get(fallback), region.defaultInstruction === null ? "switch-no-match" : "switch-default");
|
|
147
|
+
} else if (opcode === "break" || opcode === "breakc") {
|
|
148
|
+
const owner = containingRegion(regions, last.index, new Set(["loop", "switch"]));
|
|
149
|
+
if (!owner) throw new Error(`Shader IR has ${opcode} outside loop or switch at instruction ${last.index}`);
|
|
150
|
+
const target = blockAfterInstruction(owner.endInstruction);
|
|
151
|
+
if (target) addEdge(block, target, "break");else block.exits.push("break");
|
|
152
|
+
if (opcode === "breakc") addEdge(block, next, "condition-false");
|
|
153
|
+
} else if (opcode === "continue" || opcode === "continuec") {
|
|
154
|
+
const owner = containingRegion(regions, last.index, new Set(["loop"]));
|
|
155
|
+
if (!owner) throw new Error(`Shader IR has ${opcode} outside loop at instruction ${last.index}`);
|
|
156
|
+
addEdge(block, blockAtInstruction.get(owner.endInstruction), "continue");
|
|
157
|
+
if (opcode === "continuec") addEdge(block, next, "condition-false");
|
|
158
|
+
} else if (opcode === "endloop") {
|
|
159
|
+
const owner = regions.find(entry => entry.kind === "loop" && entry.endInstruction === last.index);
|
|
160
|
+
addEdge(block, blockAtInstruction.get(owner.startInstruction), "loop-back");
|
|
161
|
+
} else if (TERMINAL_EXITS.has(opcode)) {
|
|
162
|
+
block.exits.push(opcode === "abort" ? "abort" : "return");
|
|
163
|
+
} else if (CONDITIONAL_EXITS.has(opcode)) {
|
|
164
|
+
block.exits.push(opcode === "discard" ? "discard" : "return");
|
|
165
|
+
addEdge(block, next, "condition-false");
|
|
166
|
+
} else {
|
|
167
|
+
const upcomingElse = next ? elseRegion.get(next.startInstruction) : null;
|
|
168
|
+
if (upcomingElse) {
|
|
169
|
+
addEdge(block, blockAtInstruction.get(upcomingElse.endInstruction), "selection-merge");
|
|
170
|
+
} else {
|
|
171
|
+
addEdge(block, next, opcode === "loop" ? "loop-body" : "fallthrough");
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
for (const block of blocks) {
|
|
176
|
+
for (const edge of block.successors) {
|
|
177
|
+
blockById.get(edge.blockId).predecessors.push({
|
|
178
|
+
blockId: block.id,
|
|
179
|
+
kind: edge.kind
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const reachable = new Set();
|
|
184
|
+
const pending = blocks.length ? [blocks[0]] : [];
|
|
185
|
+
while (pending.length) {
|
|
186
|
+
const block = pending.shift();
|
|
187
|
+
if (reachable.has(block.id)) continue;
|
|
188
|
+
reachable.add(block.id);
|
|
189
|
+
for (const edge of block.successors) pending.push(blockById.get(edge.blockId));
|
|
190
|
+
}
|
|
191
|
+
for (const block of blocks) block.reachable = reachable.has(block.id);
|
|
192
|
+
for (const block of blocks) {
|
|
193
|
+
const predecessorBlockIds = Array.from(new Set(block.predecessors.map(edge => edge.blockId))).filter(id => block.reachable && blockById.get(id).reachable);
|
|
194
|
+
const includesEntry = block.id === blocks[0]?.id;
|
|
195
|
+
if (predecessorBlockIds.length > 1 || includesEntry && predecessorBlockIds.length > 0) {
|
|
196
|
+
block.mergeSite = {
|
|
197
|
+
kind: "control-flow-merge-site",
|
|
198
|
+
id: `merge:${block.id}`,
|
|
199
|
+
predecessorBlockIds,
|
|
200
|
+
includesEntry,
|
|
201
|
+
requiresRegisterMerge: true
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
program.controlFlow = {
|
|
206
|
+
kind: "control-flow-graph",
|
|
207
|
+
entryBlockId: blocks[0]?.id || null,
|
|
208
|
+
edgeCount: blocks.reduce((total, block) => total + block.successors.length, 0),
|
|
209
|
+
reachableBlockIds: blocks.filter(block => block.reachable).map(block => block.id),
|
|
210
|
+
unreachableBlockIds: blocks.filter(block => !block.reachable).map(block => block.id),
|
|
211
|
+
regions: regions.map((region, index) => ({
|
|
212
|
+
id: `region${index}`,
|
|
213
|
+
...region
|
|
214
|
+
}))
|
|
215
|
+
};
|
|
216
|
+
return program;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export { buildControlFlow };
|
|
220
|
+
//# sourceMappingURL=buildControlFlow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildControlFlow.js","sources":["../../../../../../src/formats/webgpu/core/ir/buildControlFlow.js"],"sourcesContent":["const CONDITIONAL_EXITS = new Set([ \"retc\", \"discard\" ]);\nconst TERMINAL_EXITS = new Set([ \"ret\", \"abort\" ]);\nconst UNSUPPORTED_FLOW = new Set([ \"call\", \"callc\", \"label\", \"interface_call\" ]);\n\nfunction collectRegions(instructions)\n{\n const regions = [];\n const stack = [];\n\n const requireTop = (kind, opcode, index) =>\n {\n const region = stack.at(-1);\n if (!region || region.kind !== kind)\n {\n throw new Error(`Shader IR has mismatched ${opcode} at instruction ${index}`);\n }\n return region;\n };\n\n for (const instruction of instructions)\n {\n const index = instruction.index;\n switch (instruction.opcodeName)\n {\n case \"if\":\n stack.push({ kind: \"selection\", startInstruction: index, elseInstruction: null });\n break;\n case \"else\":\n {\n const region = requireTop(\"selection\", \"else\", index);\n if (region.elseInstruction !== null) throw new Error(`Shader IR has duplicate else at instruction ${index}`);\n region.elseInstruction = index;\n break;\n }\n case \"endif\":\n {\n const region = requireTop(\"selection\", \"endif\", index);\n stack.pop();\n region.endInstruction = index;\n regions.push(region);\n break;\n }\n case \"loop\":\n stack.push({ kind: \"loop\", startInstruction: index });\n break;\n case \"endloop\":\n {\n const region = requireTop(\"loop\", \"endloop\", index);\n stack.pop();\n region.endInstruction = index;\n regions.push(region);\n break;\n }\n case \"switch\":\n stack.push({ kind: \"switch\", startInstruction: index, caseInstructions: [], defaultInstruction: null });\n break;\n case \"case\":\n {\n const region = requireTop(\"switch\", \"case\", index);\n region.caseInstructions.push(index);\n break;\n }\n case \"default\":\n {\n const region = requireTop(\"switch\", \"default\", index);\n if (region.defaultInstruction !== null) throw new Error(`Shader IR has duplicate default at instruction ${index}`);\n region.defaultInstruction = index;\n break;\n }\n case \"endswitch\":\n {\n const region = requireTop(\"switch\", \"endswitch\", index);\n stack.pop();\n region.endInstruction = index;\n regions.push(region);\n break;\n }\n default:\n break;\n }\n }\n\n if (stack.length)\n {\n throw new Error(\"Shader IR contains an unterminated structured control-flow region\");\n }\n return regions.sort((a, b) => a.startInstruction - b.startInstruction);\n}\n\nfunction containingRegion(regions, instructionIndex, kinds)\n{\n return regions\n .filter((region) => kinds.has(region.kind)\n && region.startInstruction < instructionIndex\n && instructionIndex < region.endInstruction)\n .sort((a, b) => b.startInstruction - a.startInstruction)[0] || null;\n}\n\nfunction addEdge(from, to, kind)\n{\n if (!to) return;\n if (!from.successors.some((edge) => edge.blockId === to.id && edge.kind === kind))\n {\n from.successors.push({ blockId: to.id, kind });\n }\n}\n\n/**\n * Adds structured CFG edges without attempting register SSA construction.\n * Join blocks receive merge-site metadata consumed by the later SSA pass.\n *\n * @param {object} program Mutable shader IR under construction.\n * @returns {object} The same program.\n */\nexport function buildControlFlow(program)\n{\n const { blocks, instructions } = program;\n const unsupported = instructions.find((instruction) => UNSUPPORTED_FLOW.has(instruction.opcodeName));\n if (unsupported)\n {\n throw new Error(`Shader IR does not yet support ${unsupported.opcodeName} control flow at instruction ${unsupported.index}`);\n }\n const regions = collectRegions(instructions);\n const blockAtInstruction = new Map();\n const blockById = new Map(blocks.map((block) => [ block.id, block ]));\n for (const block of blocks)\n {\n block.successors = [];\n block.predecessors = [];\n block.exits = [];\n block.mergeSite = null;\n for (const index of block.instructionIndices) blockAtInstruction.set(index, block);\n }\n\n const blockAfterInstruction = (index) => blockAtInstruction.get(index + 1) || null;\n const regionStartingAt = new Map(regions.map((region) => [ region.startInstruction, region ]));\n const elseRegion = new Map(regions\n .filter((region) => region.kind === \"selection\" && region.elseInstruction !== null)\n .map((region) => [ region.elseInstruction, region ]));\n\n for (const block of blocks)\n {\n const last = instructions[block.endInstruction];\n const next = blocks[block.index + 1] || null;\n const opcode = last.opcodeName;\n const region = regionStartingAt.get(last.index);\n\n if (opcode === \"if\")\n {\n const trueTarget = region.elseInstruction === next?.startInstruction\n ? blockAtInstruction.get(region.endInstruction)\n : next;\n addEdge(block, trueTarget, \"selection-true\");\n const falseInstruction = region.elseInstruction ?? region.endInstruction;\n addEdge(block, blockAtInstruction.get(falseInstruction), \"selection-false\");\n }\n else if (opcode === \"switch\")\n {\n for (const caseInstruction of region.caseInstructions)\n {\n addEdge(block, blockAtInstruction.get(caseInstruction), \"switch-case\");\n }\n const fallback = region.defaultInstruction ?? region.endInstruction;\n addEdge(block, blockAtInstruction.get(fallback), region.defaultInstruction === null ? \"switch-no-match\" : \"switch-default\");\n }\n else if (opcode === \"break\" || opcode === \"breakc\")\n {\n const owner = containingRegion(regions, last.index, new Set([ \"loop\", \"switch\" ]));\n if (!owner) throw new Error(`Shader IR has ${opcode} outside loop or switch at instruction ${last.index}`);\n const target = blockAfterInstruction(owner.endInstruction);\n if (target) addEdge(block, target, \"break\");\n else block.exits.push(\"break\");\n if (opcode === \"breakc\") addEdge(block, next, \"condition-false\");\n }\n else if (opcode === \"continue\" || opcode === \"continuec\")\n {\n const owner = containingRegion(regions, last.index, new Set([ \"loop\" ]));\n if (!owner) throw new Error(`Shader IR has ${opcode} outside loop at instruction ${last.index}`);\n addEdge(block, blockAtInstruction.get(owner.endInstruction), \"continue\");\n if (opcode === \"continuec\") addEdge(block, next, \"condition-false\");\n }\n else if (opcode === \"endloop\")\n {\n const owner = regions.find((entry) => entry.kind === \"loop\" && entry.endInstruction === last.index);\n addEdge(block, blockAtInstruction.get(owner.startInstruction), \"loop-back\");\n }\n else if (TERMINAL_EXITS.has(opcode))\n {\n block.exits.push(opcode === \"abort\" ? \"abort\" : \"return\");\n }\n else if (CONDITIONAL_EXITS.has(opcode))\n {\n block.exits.push(opcode === \"discard\" ? \"discard\" : \"return\");\n addEdge(block, next, \"condition-false\");\n }\n else\n {\n const upcomingElse = next ? elseRegion.get(next.startInstruction) : null;\n if (upcomingElse)\n {\n addEdge(block, blockAtInstruction.get(upcomingElse.endInstruction), \"selection-merge\");\n }\n else\n {\n addEdge(block, next, opcode === \"loop\" ? \"loop-body\" : \"fallthrough\");\n }\n }\n }\n\n for (const block of blocks)\n {\n for (const edge of block.successors)\n {\n blockById.get(edge.blockId).predecessors.push({ blockId: block.id, kind: edge.kind });\n }\n }\n\n const reachable = new Set();\n const pending = blocks.length ? [ blocks[0] ] : [];\n while (pending.length)\n {\n const block = pending.shift();\n if (reachable.has(block.id)) continue;\n reachable.add(block.id);\n for (const edge of block.successors) pending.push(blockById.get(edge.blockId));\n }\n for (const block of blocks) block.reachable = reachable.has(block.id);\n for (const block of blocks)\n {\n const predecessorBlockIds = Array.from(new Set(block.predecessors.map((edge) => edge.blockId)))\n .filter((id) => block.reachable && blockById.get(id).reachable);\n const includesEntry = block.id === blocks[0]?.id;\n if (predecessorBlockIds.length > 1 || (includesEntry && predecessorBlockIds.length > 0))\n {\n block.mergeSite = {\n kind: \"control-flow-merge-site\",\n id: `merge:${block.id}`,\n predecessorBlockIds,\n includesEntry,\n requiresRegisterMerge: true\n };\n }\n }\n\n program.controlFlow = {\n kind: \"control-flow-graph\",\n entryBlockId: blocks[0]?.id || null,\n edgeCount: blocks.reduce((total, block) => total + block.successors.length, 0),\n reachableBlockIds: blocks.filter((block) => block.reachable).map((block) => block.id),\n unreachableBlockIds: blocks.filter((block) => !block.reachable).map((block) => block.id),\n regions: regions.map((region, index) => ({ id: `region${index}`, ...region }))\n };\n return program;\n}\n"],"names":["CONDITIONAL_EXITS","Set","TERMINAL_EXITS","UNSUPPORTED_FLOW","collectRegions","instructions","regions","stack","requireTop","kind","opcode","index","region","at","Error","instruction","opcodeName","push","startInstruction","elseInstruction","pop","endInstruction","caseInstructions","defaultInstruction","length","sort","a","b","containingRegion","instructionIndex","kinds","filter","has","addEdge","from","to","successors","some","edge","blockId","id","buildControlFlow","program","blocks","unsupported","find","blockAtInstruction","Map","blockById","map","block","predecessors","exits","mergeSite","instructionIndices","set","blockAfterInstruction","get","regionStartingAt","elseRegion","last","next","trueTarget","falseInstruction","caseInstruction","fallback","owner","target","entry","upcomingElse","reachable","pending","shift","add","predecessorBlockIds","Array","includesEntry","requiresRegisterMerge","controlFlow","entryBlockId","edgeCount","reduce","total","reachableBlockIds","unreachableBlockIds"],"mappings":"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"}
|