From f65d756bff8d4c5cbc15bd0322a2ae8e6b896a21 Mon Sep 17 00:00:00 2001 From: Ellie Hermaszewska Date: Tue, 29 Oct 2024 14:49:26 +0800 Subject: format * format * Minor test fixes * enable checking cpp format in ci --- examples/autodiff-texture/main.cpp | 272 +- examples/cpu-com-example/main.cpp | 54 +- examples/cpu-hello-world/main.cpp | 66 +- examples/example-base/example-base.cpp | 87 +- examples/example-base/example-base.h | 42 +- examples/example-base/test-base.cpp | 15 +- examples/example-base/test-base.h | 14 +- examples/gpu-printing/gpu-printing.cpp | 159 +- examples/gpu-printing/gpu-printing.h | 50 +- examples/gpu-printing/main.cpp | 209 +- examples/hello-world/main.cpp | 46 +- examples/hello-world/vulkan-api.cpp | 30 +- examples/hello-world/vulkan-api.h | 12 +- examples/model-viewer/main.cpp | 605 +- examples/nv-aftermath-example/main.cpp | 264 +- examples/platform-test/main.cpp | 188 +- examples/ray-tracing-pipeline/main.cpp | 1076 +- examples/ray-tracing/main.cpp | 1006 +- examples/shader-object/main.cpp | 31 +- examples/shader-toy/main.cpp | 635 +- examples/triangle/main.cpp | 629 +- extras/formatting.sh | 3 +- include/slang-com-helper.h | 218 +- include/slang-com-ptr.h | 232 +- include/slang-deprecated.h | 2102 +- include/slang-gfx.h | 1056 +- include/slang-image-format-defs.h | 86 +- include/slang.h | 5630 ++--- prelude/slang-cpp-host-prelude.h | 57 +- prelude/slang-cpp-prelude.h | 362 +- prelude/slang-cpp-scalar-intrinsics.h | 591 +- prelude/slang-cpp-types-core.h | 569 +- prelude/slang-cpp-types.h | 1062 +- prelude/slang-cuda-prelude.h | 2635 ++- prelude/slang-hlsl-prelude.h | 4 +- prelude/slang-llvm.h | 322 +- prelude/slang-torch-prelude.h | 93 +- .../slang-artifact-associated-impl.cpp | 69 +- .../compiler-core/slang-artifact-associated-impl.h | 131 +- source/compiler-core/slang-artifact-associated.h | 89 +- .../slang-artifact-container-util.cpp | 240 +- .../compiler-core/slang-artifact-container-util.h | 40 +- source/compiler-core/slang-artifact-desc-util.cpp | 439 +- source/compiler-core/slang-artifact-desc-util.h | 96 +- .../slang-artifact-diagnostic-util.cpp | 41 +- .../compiler-core/slang-artifact-diagnostic-util.h | 36 +- .../compiler-core/slang-artifact-handler-impl.cpp | 565 +- source/compiler-core/slang-artifact-handler-impl.h | 63 +- source/compiler-core/slang-artifact-helper.cpp | 202 +- source/compiler-core/slang-artifact-helper.h | 239 +- source/compiler-core/slang-artifact-impl.cpp | 79 +- source/compiler-core/slang-artifact-impl.h | 107 +- .../slang-artifact-representation-impl.cpp | 63 +- .../slang-artifact-representation-impl.h | 126 +- .../compiler-core/slang-artifact-representation.h | 52 +- source/compiler-core/slang-artifact-util.cpp | 124 +- source/compiler-core/slang-artifact-util.h | 98 +- source/compiler-core/slang-artifact.h | 495 +- source/compiler-core/slang-command-line-args.cpp | 35 +- source/compiler-core/slang-command-line-args.h | 174 +- source/compiler-core/slang-core-diagnostics.cpp | 23 +- source/compiler-core/slang-core-diagnostics.h | 10 +- source/compiler-core/slang-diagnostic-sink.cpp | 179 +- source/compiler-core/slang-diagnostic-sink.h | 224 +- source/compiler-core/slang-doc-extractor.cpp | 319 +- source/compiler-core/slang-doc-extractor.h | 156 +- .../slang-downstream-compiler-set.cpp | 14 +- .../compiler-core/slang-downstream-compiler-set.h | 29 +- .../slang-downstream-compiler-util.cpp | 171 +- .../compiler-core/slang-downstream-compiler-util.h | 120 +- source/compiler-core/slang-downstream-compiler.cpp | 99 +- source/compiler-core/slang-downstream-compiler.h | 267 +- source/compiler-core/slang-dxc-compiler.cpp | 298 +- source/compiler-core/slang-dxc-compiler.h | 10 +- source/compiler-core/slang-fxc-compiler.cpp | 167 +- source/compiler-core/slang-fxc-compiler.h | 10 +- source/compiler-core/slang-gcc-compiler-util.cpp | 265 +- source/compiler-core/slang-gcc-compiler-util.h | 72 +- source/compiler-core/slang-glslang-compiler.cpp | 149 +- source/compiler-core/slang-glslang-compiler.h | 20 +- source/compiler-core/slang-include-system.cpp | 74 +- source/compiler-core/slang-include-system.h | 47 +- source/compiler-core/slang-json-diagnostic-defs.h | 8 +- source/compiler-core/slang-json-diagnostics.cpp | 13 +- source/compiler-core/slang-json-diagnostics.h | 8 +- source/compiler-core/slang-json-lexer.cpp | 182 +- source/compiler-core/slang-json-lexer.h | 42 +- source/compiler-core/slang-json-native.cpp | 171 +- source/compiler-core/slang-json-native.h | 69 +- source/compiler-core/slang-json-parser.cpp | 73 +- source/compiler-core/slang-json-parser.h | 93 +- source/compiler-core/slang-json-rpc-connection.cpp | 91 +- source/compiler-core/slang-json-rpc-connection.h | 281 +- source/compiler-core/slang-json-rpc.cpp | 51 +- source/compiler-core/slang-json-rpc.h | 109 +- .../compiler-core/slang-json-source-map-util.cpp | 146 +- source/compiler-core/slang-json-source-map-util.h | 41 +- source/compiler-core/slang-json-value.cpp | 370 +- source/compiler-core/slang-json-value.h | 301 +- .../slang-language-server-protocol.cpp | 109 +- .../compiler-core/slang-language-server-protocol.h | 85 +- source/compiler-core/slang-lexer-diagnostic-defs.h | 8 +- source/compiler-core/slang-lexer.cpp | 2484 +-- source/compiler-core/slang-lexer.h | 277 +- source/compiler-core/slang-llvm-compiler.cpp | 19 +- source/compiler-core/slang-llvm-compiler.h | 10 +- source/compiler-core/slang-metal-compiler.cpp | 177 +- source/compiler-core/slang-metal-compiler.h | 16 +- source/compiler-core/slang-misc-diagnostic-defs.h | 42 +- .../compiler-core/slang-name-convention-util.cpp | 117 +- source/compiler-core/slang-name-convention-util.h | 114 +- source/compiler-core/slang-name.cpp | 6 +- source/compiler-core/slang-name.h | 12 +- source/compiler-core/slang-nvrtc-compiler.cpp | 344 +- source/compiler-core/slang-nvrtc-compiler.h | 10 +- .../compiler-core/slang-perfect-hash-codegen.cpp | 117 +- source/compiler-core/slang-perfect-hash-codegen.h | 10 +- source/compiler-core/slang-perfect-hash.cpp | 21 +- source/compiler-core/slang-perfect-hash.h | 7 +- source/compiler-core/slang-slice-allocator.cpp | 25 +- source/compiler-core/slang-slice-allocator.h | 72 +- source/compiler-core/slang-source-embed-util.cpp | 146 +- source/compiler-core/slang-source-embed-util.h | 52 +- source/compiler-core/slang-source-loc.cpp | 230 +- source/compiler-core/slang-source-loc.h | 565 +- source/compiler-core/slang-source-map.cpp | 49 +- source/compiler-core/slang-source-map.h | 94 +- source/compiler-core/slang-spirv-core-grammar.cpp | 150 +- source/compiler-core/slang-spirv-core-grammar.h | 257 +- .../compiler-core/slang-test-server-protocol.cpp | 18 +- source/compiler-core/slang-test-server-protocol.h | 17 +- source/compiler-core/slang-tint-compiler.cpp | 250 +- source/compiler-core/slang-tint-compiler.h | 18 +- source/compiler-core/slang-token-defs.h | 133 +- source/compiler-core/slang-token.cpp | 14 +- source/compiler-core/slang-token.h | 49 +- .../slang-visual-studio-compiler-util.cpp | 151 +- .../slang-visual-studio-compiler-util.h | 43 +- .../windows/slang-win-visual-studio-util.cpp | 187 +- .../windows/slang-win-visual-studio-util.h | 32 +- source/core/slang-allocator.h | 112 +- source/core/slang-archive-file-system.cpp | 33 +- source/core/slang-archive-file-system.h | 36 +- source/core/slang-array-view.h | 329 +- source/core/slang-array.h | 395 +- source/core/slang-basic.h | 10 +- source/core/slang-blob.cpp | 34 +- source/core/slang-blob.h | 166 +- source/core/slang-byte-encode-util.cpp | 78 +- source/core/slang-byte-encode-util.h | 139 +- source/core/slang-castable.cpp | 8 +- source/core/slang-castable.h | 81 +- source/core/slang-char-encode.cpp | 192 +- source/core/slang-char-encode.h | 57 +- source/core/slang-char-util.cpp | 9 +- source/core/slang-char-util.h | 93 +- source/core/slang-chunked-list.h | 37 +- source/core/slang-com-object.h | 68 +- source/core/slang-command-line.cpp | 12 +- source/core/slang-command-line.h | 113 +- source/core/slang-command-options-writer.cpp | 192 +- source/core/slang-command-options-writer.h | 37 +- source/core/slang-command-options.cpp | 129 +- source/core/slang-command-options.h | 237 +- source/core/slang-common.h | 289 +- source/core/slang-compression-system.h | 62 +- source/core/slang-crypto.cpp | 106 +- source/core/slang-crypto.h | 262 +- source/core/slang-deflate-compression-system.cpp | 54 +- source/core/slang-deflate-compression-system.h | 6 +- source/core/slang-dictionary.h | 1306 +- source/core/slang-exception.h | 96 +- source/core/slang-file-system.cpp | 362 +- source/core/slang-file-system.h | 303 +- source/core/slang-free-list.cpp | 324 +- source/core/slang-free-list.h | 236 +- source/core/slang-func-ptr.h | 47 +- source/core/slang-hash.h | 379 +- source/core/slang-hex-dump-util.cpp | 73 +- source/core/slang-hex-dump-util.h | 45 +- source/core/slang-http.cpp | 69 +- source/core/slang-http.h | 127 +- source/core/slang-implicit-directory-collector.cpp | 23 +- source/core/slang-implicit-directory-collector.h | 56 +- source/core/slang-io.cpp | 2093 +- source/core/slang-io.h | 548 +- source/core/slang-linked-list.h | 46 +- source/core/slang-list.h | 994 +- source/core/slang-lz4-compression-system.cpp | 55 +- source/core/slang-lz4-compression-system.h | 6 +- source/core/slang-math.h | 460 +- source/core/slang-memory-arena.cpp | 54 +- source/core/slang-memory-arena.h | 279 +- source/core/slang-memory-file-system.cpp | 61 +- source/core/slang-memory-file-system.h | 93 +- source/core/slang-name-value.cpp | 74 +- source/core/slang-name-value.h | 115 +- source/core/slang-offset-container.cpp | 31 +- source/core/slang-offset-container.h | 336 +- source/core/slang-performance-profiler.cpp | 190 +- source/core/slang-performance-profiler.h | 15 +- source/core/slang-persistent-cache.cpp | 29 +- source/core/slang-persistent-cache.h | 6 +- source/core/slang-platform.cpp | 115 +- source/core/slang-platform.h | 277 +- source/core/slang-process-util.cpp | 27 +- source/core/slang-process-util.h | 18 +- source/core/slang-process.h | 66 +- source/core/slang-random-generator.cpp | 21 +- source/core/slang-random-generator.h | 81 +- source/core/slang-range.h | 37 +- source/core/slang-render-api-util.cpp | 103 +- source/core/slang-render-api-util.h | 55 +- source/core/slang-riff-file-system.cpp | 69 +- source/core/slang-riff-file-system.h | 56 +- source/core/slang-riff.cpp | 143 +- source/core/slang-riff.h | 299 +- source/core/slang-rtti-info.cpp | 80 +- source/core/slang-rtti-info.h | 256 +- source/core/slang-rtti-util.cpp | 386 +- source/core/slang-rtti-util.h | 80 +- source/core/slang-secure-crt.h | 84 +- source/core/slang-semantic-version.cpp | 76 +- source/core/slang-semantic-version.h | 99 +- source/core/slang-shared-library.cpp | 29 +- source/core/slang-shared-library.h | 65 +- source/core/slang-short-list.h | 772 +- source/core/slang-signal.cpp | 33 +- source/core/slang-signal.h | 14 +- source/core/slang-smart-pointer.h | 518 +- source/core/slang-stable-hash.h | 128 +- source/core/slang-std-writers.cpp | 17 +- source/core/slang-std-writers.h | 33 +- source/core/slang-stream.cpp | 162 +- source/core/slang-stream.h | 211 +- source/core/slang-string-escape-util.cpp | 449 +- source/core/slang-string-escape-util.h | 110 +- source/core/slang-string-slice-index-map.cpp | 8 +- source/core/slang-string-slice-index-map.h | 50 +- source/core/slang-string-slice-pool.cpp | 39 +- source/core/slang-string-slice-pool.h | 78 +- source/core/slang-string-util.cpp | 184 +- source/core/slang-string-util.h | 276 +- source/core/slang-string.cpp | 1101 +- source/core/slang-string.h | 1514 +- source/core/slang-test-tool-util.cpp | 68 +- source/core/slang-test-tool-util.h | 76 +- source/core/slang-text-io.cpp | 137 +- source/core/slang-text-io.h | 161 +- source/core/slang-token-reader.cpp | 1194 +- source/core/slang-token-reader.h | 533 +- source/core/slang-type-convert-util.cpp | 37 +- source/core/slang-type-convert-util.h | 7 +- source/core/slang-type-text-util.cpp | 343 +- source/core/slang-type-text-util.h | 79 +- source/core/slang-type-traits.h | 82 +- source/core/slang-uint-set.cpp | 42 +- source/core/slang-uint-set.h | 114 +- source/core/slang-virtual-object-pool.h | 8 +- source/core/slang-writer.cpp | 39 +- source/core/slang-writer.h | 161 +- source/core/slang-zip-file-system.cpp | 250 +- source/core/slang-zip-file-system.h | 9 +- source/core/unix/slang-unix-process.cpp | 152 +- source/core/windows/slang-win-process.cpp | 213 +- .../slang-embedded-core-module-source.cpp | 644 +- .../slang-embedded-core-module.cpp | 7 +- source/slang-glslang/slang-glslang.cpp | 411 +- source/slang-glslang/slang-glslang.h | 80 +- source/slang-llvm/slang-llvm-filecheck.cpp | 33 +- source/slang-llvm/slang-llvm.cpp | 369 +- .../slang-record-replay/record/output-stream.cpp | 77 +- source/slang-record-replay/record/output-stream.h | 66 +- .../record/parameter-recorder.cpp | 184 +- .../record/parameter-recorder.h | 139 +- .../slang-record-replay/record/record-manager.cpp | 139 +- source/slang-record-replay/record/record-manager.h | 45 +- .../record/slang-component-type.cpp | 603 +- .../record/slang-component-type.h | 148 +- .../record/slang-composite-component-type.cpp | 31 +- .../record/slang-composite-component-type.h | 69 +- .../record/slang-entrypoint.cpp | 46 +- .../slang-record-replay/record/slang-entrypoint.h | 319 +- .../record/slang-filesystem.cpp | 253 +- .../slang-record-replay/record/slang-filesystem.h | 87 +- .../record/slang-global-session.cpp | 773 +- .../record/slang-global-session.h | 173 +- source/slang-record-replay/record/slang-module.cpp | 370 +- source/slang-record-replay/record/slang-module.h | 368 +- .../slang-record-replay/record/slang-session.cpp | 866 +- source/slang-record-replay/record/slang-session.h | 183 +- .../record/slang-type-conformance.cpp | 44 +- .../record/slang-type-conformance.h | 308 +- .../slang-record-replay/replay/decoder-consumer.h | 613 +- .../slang-record-replay/replay/decoder-helper.cpp | 91 +- source/slang-record-replay/replay/decoder-helper.h | 186 +- .../slang-record-replay/replay/json-consumer.cpp | 4101 ++-- source/slang-record-replay/replay/json-consumer.h | 757 +- .../replay/parameter-decoder.cpp | 398 +- .../slang-record-replay/replay/parameter-decoder.h | 302 +- .../replay/recordFile-processor.cpp | 220 +- .../replay/recordFile-processor.h | 64 +- .../slang-record-replay/replay/replay-consumer.cpp | 2336 ++- .../slang-record-replay/replay/replay-consumer.h | 781 +- .../slang-record-replay/replay/slang-decoder.cpp | 4595 +++-- source/slang-record-replay/replay/slang-decoder.h | 390 +- source/slang-record-replay/util/emum-to-string.h | 410 +- source/slang-record-replay/util/record-format.h | 404 +- source/slang-record-replay/util/record-utility.cpp | 111 +- source/slang-record-replay/util/record-utility.h | 52 +- source/slang-rt/slang-rt.cpp | 8 +- source/slang-rt/slang-rt.h | 19 +- source/slang-wasm/slang-wasm-bindings.cpp | 55 +- source/slang-wasm/slang-wasm.cpp | 651 +- source/slang-wasm/slang-wasm.h | 271 +- source/slang/slang-api.cpp | 418 +- source/slang/slang-artifact-output-util.cpp | 104 +- source/slang/slang-artifact-output-util.h | 76 +- source/slang/slang-ast-all.h | 3 +- source/slang/slang-ast-base.cpp | 63 +- source/slang/slang-ast-base.h | 306 +- source/slang/slang-ast-builder.cpp | 202 +- source/slang/slang-ast-builder.h | 309 +- source/slang/slang-ast-decl-ref.cpp | 82 +- source/slang/slang-ast-decl.cpp | 20 +- source/slang/slang-ast-decl.h | 148 +- source/slang/slang-ast-dump.cpp | 234 +- source/slang/slang-ast-dump.h | 5 +- source/slang/slang-ast-expr.h | 219 +- source/slang/slang-ast-iterator.h | 64 +- source/slang/slang-ast-modifier.cpp | 12 +- source/slang/slang-ast-modifier.h | 688 +- source/slang/slang-ast-natural-layout.cpp | 45 +- source/slang/slang-ast-natural-layout.h | 91 +- source/slang/slang-ast-print.cpp | 92 +- source/slang/slang-ast-print.h | 128 +- source/slang/slang-ast-reflect.cpp | 60 +- source/slang/slang-ast-reflect.h | 61 +- source/slang/slang-ast-stmt.h | 65 +- source/slang/slang-ast-support-types.cpp | 11 +- source/slang/slang-ast-support-types.h | 2775 +-- source/slang/slang-ast-synthesis.cpp | 16 +- source/slang/slang-ast-synthesis.h | 13 +- source/slang/slang-ast-type.cpp | 336 +- source/slang/slang-ast-type.h | 216 +- source/slang/slang-ast-val.cpp | 482 +- source/slang/slang-ast-val.h | 235 +- source/slang/slang-capability.cpp | 491 +- source/slang/slang-capability.h | 121 +- source/slang/slang-check-conformance.cpp | 618 +- source/slang/slang-check-constraint.cpp | 2050 +- source/slang/slang-check-conversion.cpp | 2433 ++- source/slang/slang-check-decl.cpp | 20443 ++++++++++--------- source/slang/slang-check-expr.cpp | 8539 ++++---- source/slang/slang-check-impl.h | 5191 +++-- source/slang/slang-check-inheritance.cpp | 1961 +- source/slang/slang-check-modifier.cpp | 2986 +-- source/slang/slang-check-overload.cpp | 4674 ++--- source/slang/slang-check-resolve-val.cpp | 10 +- source/slang/slang-check-shader.cpp | 2997 +-- source/slang/slang-check-stmt.cpp | 1196 +- source/slang/slang-check-type.cpp | 716 +- source/slang/slang-check.cpp | 343 +- source/slang/slang-check.h | 31 +- source/slang/slang-compiler-options.cpp | 583 +- source/slang/slang-compiler-options.h | 638 +- source/slang/slang-compiler-tu.cpp | 474 +- source/slang/slang-compiler.cpp | 4229 ++-- source/slang/slang-compiler.h | 6027 +++--- source/slang/slang-container-pool.h | 11 +- source/slang/slang-content-assist-info.h | 6 +- source/slang/slang-core-module-textures.cpp | 238 +- source/slang/slang-core-module-textures.h | 41 +- source/slang/slang-core-module.cpp | 25 +- source/slang/slang-diagnostic-defs.h | 2596 ++- source/slang/slang-diagnostics.cpp | 44 +- source/slang/slang-diagnostics.h | 49 +- source/slang/slang-doc-ast.cpp | 34 +- source/slang/slang-doc-ast.h | 43 +- source/slang/slang-doc-markdown-writer.cpp | 512 +- source/slang/slang-doc-markdown-writer.h | 67 +- source/slang/slang-emit-base.cpp | 3 +- source/slang/slang-emit-base.h | 5 +- source/slang/slang-emit-c-like.cpp | 1663 +- source/slang/slang-emit-c-like.h | 394 +- source/slang/slang-emit-cpp.cpp | 761 +- source/slang/slang-emit-cpp.h | 75 +- source/slang/slang-emit-cuda.cpp | 591 +- source/slang/slang-emit-cuda.h | 69 +- source/slang/slang-emit-glsl.cpp | 1749 +- source/slang/slang-emit-glsl.h | 124 +- source/slang/slang-emit-hlsl.cpp | 1036 +- source/slang/slang-emit-hlsl.h | 80 +- source/slang/slang-emit-metal.cpp | 868 +- source/slang/slang-emit-metal.h | 44 +- source/slang/slang-emit-precedence.cpp | 70 +- source/slang/slang-emit-precedence.h | 27 +- source/slang/slang-emit-source-writer.cpp | 124 +- source/slang/slang-emit-source-writer.h | 58 +- source/slang/slang-emit-spirv-ops-debug-info-ext.h | 500 +- source/slang/slang-emit-spirv-ops.h | 840 +- source/slang/slang-emit-spirv.cpp | 3505 ++-- source/slang/slang-emit-torch.cpp | 204 +- source/slang/slang-emit-torch.h | 11 +- source/slang/slang-emit-wgsl.cpp | 1112 +- source/slang/slang-emit-wgsl.h | 31 +- source/slang/slang-emit.cpp | 687 +- source/slang/slang-glsl-extension-tracker.cpp | 39 +- source/slang/slang-glsl-extension-tracker.h | 22 +- .../slang/slang-hlsl-to-vulkan-layout-options.cpp | 61 +- source/slang/slang-hlsl-to-vulkan-layout-options.h | 150 +- source/slang/slang-intrinsic-expand.cpp | 203 +- source/slang/slang-intrinsic-expand.h | 20 +- source/slang/slang-ir-addr-inst-elimination.cpp | 55 +- source/slang/slang-ir-addr-inst-elimination.h | 6 +- source/slang/slang-ir-address-analysis.cpp | 251 +- source/slang/slang-ir-address-analysis.h | 30 +- source/slang/slang-ir-any-value-inference.cpp | 359 +- source/slang/slang-ir-any-value-inference.h | 8 +- source/slang/slang-ir-any-value-marshalling.cpp | 938 +- source/slang/slang-ir-any-value-marshalling.h | 21 +- source/slang/slang-ir-augment-make-existential.cpp | 15 +- source/slang/slang-ir-autodiff-cfg-norm.cpp | 97 +- source/slang/slang-ir-autodiff-cfg-norm.h | 36 +- source/slang/slang-ir-autodiff-fwd.cpp | 750 +- source/slang/slang-ir-autodiff-fwd.h | 23 +- source/slang/slang-ir-autodiff-pairs.cpp | 74 +- source/slang/slang-ir-autodiff-pairs.h | 17 +- source/slang/slang-ir-autodiff-primal-hoist.cpp | 504 +- source/slang/slang-ir-autodiff-primal-hoist.h | 545 +- source/slang/slang-ir-autodiff-propagate.h | 23 +- source/slang/slang-ir-autodiff-region.cpp | 87 +- source/slang/slang-ir-autodiff-region.h | 39 +- source/slang/slang-ir-autodiff-rev.cpp | 2386 +-- source/slang/slang-ir-autodiff-rev.h | 129 +- .../slang/slang-ir-autodiff-transcriber-base.cpp | 489 +- source/slang/slang-ir-autodiff-transcriber-base.h | 62 +- source/slang/slang-ir-autodiff-transpose.h | 1616 +- source/slang/slang-ir-autodiff-unzip.cpp | 114 +- source/slang/slang-ir-autodiff-unzip.h | 249 +- source/slang/slang-ir-autodiff.cpp | 1102 +- source/slang/slang-ir-autodiff.h | 236 +- source/slang/slang-ir-bind-existentials.cpp | 82 +- source/slang/slang-ir-bind-existentials.h | 8 +- source/slang/slang-ir-bit-field-accessors.cpp | 44 +- source/slang/slang-ir-bit-field-accessors.h | 6 +- source/slang/slang-ir-byte-address-legalize.cpp | 615 +- source/slang/slang-ir-byte-address-legalize.h | 30 +- source/slang/slang-ir-call-graph.cpp | 53 +- source/slang/slang-ir-call-graph.h | 12 +- source/slang/slang-ir-check-differentiability.cpp | 221 +- source/slang/slang-ir-check-recursive-type.cpp | 82 +- source/slang/slang-ir-check-recursive-type.h | 10 +- .../slang/slang-ir-check-shader-parameter-type.cpp | 93 +- .../slang/slang-ir-check-shader-parameter-type.h | 16 +- source/slang/slang-ir-check-unsupported-inst.cpp | 132 +- source/slang/slang-ir-check-unsupported-inst.h | 10 +- source/slang/slang-ir-cleanup-void.cpp | 275 +- source/slang/slang-ir-cleanup-void.h | 11 +- source/slang/slang-ir-clone.cpp | 101 +- source/slang/slang-ir-clone.h | 191 +- source/slang/slang-ir-collect-global-uniforms.cpp | 42 +- source/slang/slang-ir-collect-global-uniforms.h | 12 +- source/slang/slang-ir-com-interface.cpp | 40 +- source/slang/slang-ir-com-interface.h | 6 +- source/slang/slang-ir-composite-reg-to-mem.cpp | 307 +- source/slang/slang-ir-composite-reg-to-mem.h | 14 +- source/slang/slang-ir-constexpr.cpp | 199 +- source/slang/slang-ir-constexpr.h | 10 +- source/slang/slang-ir-dce.cpp | 78 +- source/slang/slang-ir-dce.h | 62 +- .../slang-ir-deduplicate-generic-children.cpp | 5 +- .../slang/slang-ir-deduplicate-generic-children.h | 12 +- source/slang/slang-ir-deduplicate.cpp | 110 +- source/slang/slang-ir-defunctionalization.cpp | 4 +- source/slang/slang-ir-defunctionalization.h | 24 +- source/slang/slang-ir-diff-call.cpp | 35 +- source/slang/slang-ir-diff-call.h | 18 +- source/slang/slang-ir-dll-export.cpp | 17 +- source/slang/slang-ir-dll-export.h | 10 +- source/slang/slang-ir-dll-import.cpp | 48 +- source/slang/slang-ir-dll-import.h | 12 +- source/slang/slang-ir-dominators.cpp | 162 +- source/slang/slang-ir-dominators.h | 356 +- ...r-early-raytracing-intrinsic-simplification.cpp | 208 +- ...-ir-early-raytracing-intrinsic-simplification.h | 17 +- .../slang/slang-ir-eliminate-multilevel-break.cpp | 93 +- source/slang/slang-ir-eliminate-multilevel-break.h | 10 +- source/slang/slang-ir-eliminate-phis.cpp | 92 +- source/slang/slang-ir-eliminate-phis.h | 44 +- source/slang/slang-ir-entry-point-pass.cpp | 6 +- source/slang/slang-ir-entry-point-pass.h | 4 +- .../slang/slang-ir-entry-point-raw-ptr-params.cpp | 23 +- source/slang/slang-ir-entry-point-raw-ptr-params.h | 7 +- source/slang/slang-ir-entry-point-uniforms.cpp | 74 +- source/slang/slang-ir-entry-point-uniforms.h | 13 +- source/slang/slang-ir-explicit-global-context.cpp | 140 +- source/slang/slang-ir-explicit-global-context.h | 8 +- source/slang/slang-ir-explicit-global-init.cpp | 34 +- source/slang/slang-ir-explicit-global-init.h | 7 +- source/slang/slang-ir-extract-value-from-type.cpp | 93 +- source/slang/slang-ir-extract-value-from-type.h | 8 +- source/slang/slang-ir-fuse-satcoop.cpp | 177 +- source/slang/slang-ir-fuse-satcoop.h | 12 +- .../slang/slang-ir-generics-lowering-context.cpp | 394 +- source/slang/slang-ir-generics-lowering-context.h | 250 +- source/slang/slang-ir-glsl-legalize.cpp | 1861 +- source/slang/slang-ir-glsl-legalize.h | 14 +- source/slang/slang-ir-glsl-liveness.cpp | 73 +- source/slang/slang-ir-glsl-liveness.h | 14 +- source/slang/slang-ir-hlsl-legalize.cpp | 122 +- source/slang/slang-ir-hlsl-legalize.h | 4 +- source/slang/slang-ir-init-local-var.cpp | 8 +- source/slang/slang-ir-init-local-var.h | 12 +- source/slang/slang-ir-inline.cpp | 276 +- source/slang/slang-ir-inline.h | 55 +- source/slang/slang-ir-insert-debug-value-store.cpp | 333 +- source/slang/slang-ir-insert-debug-value-store.h | 6 +- source/slang/slang-ir-inst-pass-base.h | 217 +- source/slang/slang-ir-insts.h | 2292 +-- source/slang/slang-ir-layout.cpp | 466 +- source/slang/slang-ir-layout.h | 88 +- .../slang/slang-ir-legalize-array-return-type.cpp | 8 +- source/slang/slang-ir-legalize-array-return-type.h | 10 +- source/slang/slang-ir-legalize-image-subscript.cpp | 326 +- source/slang/slang-ir-legalize-image-subscript.h | 8 +- source/slang/slang-ir-legalize-mesh-outputs.cpp | 25 +- source/slang/slang-ir-legalize-mesh-outputs.h | 8 +- source/slang/slang-ir-legalize-types.cpp | 1822 +- .../slang-ir-legalize-uniform-buffer-load.cpp | 9 +- .../slang/slang-ir-legalize-uniform-buffer-load.h | 8 +- source/slang/slang-ir-legalize-varying-params.cpp | 477 +- source/slang/slang-ir-legalize-varying-params.h | 76 +- source/slang/slang-ir-legalize-vector-types.cpp | 316 +- source/slang/slang-ir-legalize-vector-types.h | 14 +- source/slang/slang-ir-link.cpp | 809 +- source/slang/slang-ir-link.h | 52 +- source/slang/slang-ir-liveness.cpp | 611 +- source/slang/slang-ir-liveness.h | 179 +- source/slang/slang-ir-loop-inversion.cpp | 170 +- source/slang/slang-ir-loop-inversion.h | 9 +- source/slang/slang-ir-loop-unroll.cpp | 82 +- source/slang/slang-ir-loop-unroll.h | 38 +- ...g-ir-lower-append-consume-structured-buffer.cpp | 553 +- ...ang-ir-lower-append-consume-structured-buffer.h | 19 +- source/slang/slang-ir-lower-binding-query.cpp | 912 +- source/slang/slang-ir-lower-binding-query.h | 24 +- source/slang/slang-ir-lower-bit-cast.cpp | 70 +- source/slang/slang-ir-lower-bit-cast.h | 6 +- .../slang/slang-ir-lower-buffer-element-type.cpp | 1821 +- source/slang/slang-ir-lower-buffer-element-type.h | 33 +- source/slang/slang-ir-lower-com-methods.cpp | 36 +- source/slang/slang-ir-lower-com-methods.h | 5 +- .../slang-ir-lower-combined-texture-sampler.cpp | 377 +- .../slang-ir-lower-combined-texture-sampler.h | 19 +- source/slang/slang-ir-lower-cuda-builtin-types.cpp | 796 +- source/slang/slang-ir-lower-cuda-builtin-types.h | 82 +- source/slang/slang-ir-lower-error-handling.cpp | 33 +- source/slang/slang-ir-lower-error-handling.h | 12 +- source/slang/slang-ir-lower-existential.cpp | 474 +- source/slang/slang-ir-lower-existential.h | 10 +- source/slang/slang-ir-lower-expand-type.cpp | 261 +- source/slang/slang-ir-lower-expand-type.h | 50 +- source/slang/slang-ir-lower-generic-call.cpp | 653 +- source/slang/slang-ir-lower-generic-call.h | 11 +- source/slang/slang-ir-lower-generic-function.cpp | 678 +- source/slang/slang-ir-lower-generic-function.h | 25 +- source/slang/slang-ir-lower-generic-type.cpp | 116 +- source/slang/slang-ir-lower-generic-type.h | 11 +- source/slang/slang-ir-lower-generics.cpp | 487 +- source/slang/slang-ir-lower-generics.h | 23 +- source/slang/slang-ir-lower-glsl-ssbo-types.cpp | 310 +- source/slang/slang-ir-lower-glsl-ssbo-types.h | 16 +- source/slang/slang-ir-lower-l-value-cast.cpp | 63 +- source/slang/slang-ir-lower-l-value-cast.h | 20 +- source/slang/slang-ir-lower-optional-type.cpp | 475 +- source/slang/slang-ir-lower-optional-type.h | 12 +- source/slang/slang-ir-lower-reinterpret.cpp | 48 +- source/slang/slang-ir-lower-reinterpret.h | 6 +- source/slang/slang-ir-lower-result-type.cpp | 492 +- source/slang/slang-ir-lower-result-type.h | 12 +- source/slang/slang-ir-lower-tuple-types.cpp | 661 +- source/slang/slang-ir-lower-tuple-types.h | 12 +- source/slang/slang-ir-lower-witness-lookup.cpp | 79 +- source/slang/slang-ir-lower-witness-lookup.h | 17 +- source/slang/slang-ir-marshal-native-call.cpp | 506 +- source/slang/slang-ir-marshal-native-call.h | 115 +- source/slang/slang-ir-metadata.cpp | 34 +- source/slang/slang-ir-metadata.h | 2 +- source/slang/slang-ir-metal-legalize.cpp | 3136 +-- source/slang/slang-ir-metal-legalize.h | 6 +- source/slang/slang-ir-missing-return.cpp | 23 +- source/slang/slang-ir-missing-return.h | 10 +- source/slang/slang-ir-obfuscate-loc.cpp | 88 +- source/slang/slang-ir-obfuscate-loc.h | 9 +- source/slang/slang-ir-operator-shift-overflow.cpp | 64 +- source/slang/slang-ir-operator-shift-overflow.h | 14 +- .../slang/slang-ir-optix-entry-point-uniforms.cpp | 72 +- source/slang/slang-ir-optix-entry-point-uniforms.h | 2 +- source/slang/slang-ir-peephole.cpp | 257 +- source/slang/slang-ir-peephole.h | 40 +- .../slang/slang-ir-propagate-func-properties.cpp | 35 +- source/slang/slang-ir-propagate-func-properties.h | 2 +- source/slang/slang-ir-pytorch-cpp-binding.cpp | 601 +- source/slang/slang-ir-pytorch-cpp-binding.h | 3 +- source/slang/slang-ir-reachability.cpp | 127 +- source/slang/slang-ir-reachability.h | 5 +- source/slang/slang-ir-redundancy-removal.cpp | 34 +- source/slang/slang-ir-redundancy-removal.h | 14 +- .../slang/slang-ir-remove-unused-generic-param.cpp | 19 +- .../slang/slang-ir-remove-unused-generic-param.h | 6 +- source/slang/slang-ir-resolve-texture-format.cpp | 158 +- source/slang/slang-ir-resolve-texture-format.h | 2 +- source/slang/slang-ir-restructure-scoping.cpp | 119 +- source/slang/slang-ir-restructure-scoping.h | 2 +- source/slang/slang-ir-restructure.cpp | 1111 +- source/slang/slang-ir-restructure.h | 429 +- source/slang/slang-ir-sccp.cpp | 433 +- source/slang/slang-ir-sccp.h | 39 +- source/slang/slang-ir-simplify-cfg.cpp | 127 +- source/slang/slang-ir-simplify-cfg.h | 30 +- source/slang/slang-ir-simplify-for-emit.cpp | 80 +- source/slang/slang-ir-simplify-for-emit.h | 8 +- source/slang/slang-ir-single-return.cpp | 17 +- source/slang/slang-ir-single-return.h | 14 +- source/slang/slang-ir-specialize-address-space.cpp | 561 +- source/slang/slang-ir-specialize-address-space.h | 42 +- source/slang/slang-ir-specialize-arrays.cpp | 8 +- source/slang/slang-ir-specialize-arrays.h | 32 +- .../slang/slang-ir-specialize-buffer-load-arg.cpp | 10 +- source/slang/slang-ir-specialize-buffer-load-arg.h | 64 +- source/slang/slang-ir-specialize-dispatch.cpp | 44 +- source/slang/slang-ir-specialize-dispatch.h | 2 +- ...ir-specialize-dynamic-associatedtype-lookup.cpp | 112 +- source/slang/slang-ir-specialize-function-call.cpp | 167 +- source/slang/slang-ir-specialize-function-call.h | 52 +- source/slang/slang-ir-specialize-matrix-layout.cpp | 58 +- source/slang/slang-ir-specialize-matrix-layout.h | 14 +- source/slang/slang-ir-specialize-resources.cpp | 316 +- source/slang/slang-ir-specialize-resources.h | 46 +- source/slang/slang-ir-specialize-target-switch.cpp | 149 +- source/slang/slang-ir-specialize-target-switch.h | 14 +- source/slang/slang-ir-specialize.cpp | 393 +- source/slang/slang-ir-specialize.h | 9 +- source/slang/slang-ir-spirv-legalize.cpp | 627 +- source/slang/slang-ir-spirv-legalize.h | 37 +- source/slang/slang-ir-spirv-snippet.cpp | 115 +- source/slang/slang-ir-spirv-snippet.h | 22 +- source/slang/slang-ir-ssa-register-allocate.cpp | 46 +- source/slang/slang-ir-ssa-register-allocate.h | 7 +- source/slang/slang-ir-ssa-simplification.cpp | 261 +- source/slang/slang-ir-ssa-simplification.h | 67 +- source/slang/slang-ir-ssa.cpp | 226 +- source/slang/slang-ir-ssa.h | 14 +- source/slang/slang-ir-string-hash.cpp | 16 +- source/slang/slang-ir-string-hash.h | 9 +- source/slang/slang-ir-strip-cached-dict.cpp | 10 +- source/slang/slang-ir-strip-cached-dict.h | 10 +- source/slang/slang-ir-strip-witness-tables.cpp | 8 +- source/slang/slang-ir-strip-witness-tables.h | 6 +- source/slang/slang-ir-strip.cpp | 38 +- source/slang/slang-ir-strip.h | 20 +- source/slang/slang-ir-synthesize-active-mask.cpp | 179 +- source/slang/slang-ir-synthesize-active-mask.h | 28 +- .../slang/slang-ir-translate-glsl-global-var.cpp | 528 +- source/slang/slang-ir-translate-glsl-global-var.h | 12 +- source/slang/slang-ir-uniformity.cpp | 553 +- source/slang/slang-ir-uniformity.h | 8 +- source/slang/slang-ir-use-uninitialized-values.cpp | 1098 +- source/slang/slang-ir-use-uninitialized-values.h | 10 +- source/slang/slang-ir-user-type-hint.cpp | 9 +- source/slang/slang-ir-user-type-hint.h | 6 +- source/slang/slang-ir-util.cpp | 653 +- source/slang/slang-ir-util.h | 126 +- source/slang/slang-ir-validate.cpp | 652 +- source/slang/slang-ir-validate.h | 66 +- .../slang/slang-ir-variable-scope-correction.cpp | 120 +- source/slang/slang-ir-variable-scope-correction.h | 2 +- source/slang/slang-ir-vk-invert-y.cpp | 35 +- source/slang/slang-ir-vk-invert-y.h | 8 +- source/slang/slang-ir-wgsl-legalize.cpp | 643 +- source/slang/slang-ir-wgsl-legalize.h | 6 +- source/slang/slang-ir-witness-table-wrapper.cpp | 404 +- source/slang/slang-ir-witness-table-wrapper.h | 31 +- source/slang/slang-ir-wrap-structured-buffers.cpp | 258 +- source/slang/slang-ir-wrap-structured-buffers.h | 16 +- source/slang/slang-ir.cpp | 14841 +++++++------- source/slang/slang-ir.h | 1057 +- source/slang/slang-language-server-ast-lookup.cpp | 106 +- source/slang/slang-language-server-ast-lookup.h | 2 +- source/slang/slang-language-server-auto-format.cpp | 63 +- source/slang/slang-language-server-auto-format.h | 10 +- source/slang/slang-language-server-completion.cpp | 169 +- source/slang/slang-language-server-completion.h | 22 +- .../slang-language-server-document-symbols.cpp | 369 +- .../slang/slang-language-server-document-symbols.h | 9 +- source/slang/slang-language-server-inlay-hints.cpp | 34 +- source/slang/slang-language-server-inlay-hints.h | 11 +- .../slang-language-server-semantic-tokens.cpp | 104 +- .../slang/slang-language-server-semantic-tokens.h | 21 +- source/slang/slang-language-server.cpp | 528 +- source/slang/slang-language-server.h | 86 +- source/slang/slang-legalize-types.cpp | 377 +- source/slang/slang-legalize-types.h | 442 +- source/slang/slang-lookup-spirv.h | 3 +- source/slang/slang-lookup.cpp | 494 +- source/slang/slang-lookup.h | 82 +- source/slang/slang-lower-to-ir.cpp | 3621 ++-- source/slang/slang-lower-to-ir.h | 75 +- source/slang/slang-mangle.cpp | 1382 +- source/slang/slang-mangle.h | 34 +- source/slang/slang-mangled-lexer.cpp | 36 +- source/slang/slang-mangled-lexer.h | 18 +- source/slang/slang-module-library.cpp | 44 +- source/slang/slang-module-library.h | 33 +- source/slang/slang-options.cpp | 1887 +- source/slang/slang-options.h | 9 +- source/slang/slang-parameter-binding.cpp | 1582 +- source/slang/slang-parameter-binding.h | 15 +- source/slang/slang-parser.cpp | 13777 +++++++------ source/slang/slang-parser.h | 77 +- source/slang/slang-preprocessor.cpp | 1669 +- source/slang/slang-preprocessor.h | 72 +- source/slang/slang-profile-defs.h | 364 +- source/slang/slang-profile.cpp | 22 +- source/slang/slang-profile.h | 193 +- source/slang/slang-ref-object-reflect.cpp | 79 +- source/slang/slang-ref-object-reflect.h | 46 +- source/slang/slang-reflection-api.cpp | 3124 +-- source/slang/slang-repro.cpp | 487 +- source/slang/slang-repro.h | 144 +- source/slang/slang-serialize-ast-type-info.h | 140 +- source/slang/slang-serialize-ast.cpp | 94 +- source/slang/slang-serialize-ast.h | 30 +- source/slang/slang-serialize-container.cpp | 392 +- source/slang/slang-serialize-container.h | 103 +- source/slang/slang-serialize-factory.cpp | 22 +- source/slang/slang-serialize-factory.h | 14 +- source/slang/slang-serialize-ir-types.cpp | 85 +- source/slang/slang-serialize-ir-types.h | 184 +- source/slang/slang-serialize-ir.cpp | 404 +- source/slang/slang-serialize-ir.h | 123 +- source/slang/slang-serialize-misc-type-info.h | 106 +- source/slang/slang-serialize-reflection.cpp | 30 +- source/slang/slang-serialize-reflection.h | 36 +- source/slang/slang-serialize-source-loc.cpp | 163 +- source/slang/slang-serialize-source-loc.h | 144 +- source/slang/slang-serialize-type-info.h | 224 +- source/slang/slang-serialize-types.cpp | 124 +- source/slang/slang-serialize-types.h | 163 +- source/slang/slang-serialize-value-type-info.h | 106 +- source/slang/slang-serialize.cpp | 169 +- source/slang/slang-serialize.h | 374 +- source/slang/slang-spirv-val.cpp | 11 +- source/slang/slang-spirv-val.h | 4 +- source/slang/slang-syntax.cpp | 1089 +- source/slang/slang-syntax.h | 592 +- source/slang/slang-type-layout.cpp | 1927 +- source/slang/slang-type-layout.h | 764 +- source/slang/slang-type-system-shared.h | 184 +- source/slang/slang-value-reflect.cpp | 6 +- source/slang/slang-value-reflect.h | 3 +- source/slang/slang-visitor.h | 138 +- source/slang/slang-workspace-version.cpp | 69 +- source/slang/slang-workspace-version.h | 364 +- source/slang/slang.cpp | 1944 +- source/slangc/main.cpp | 33 +- tests/bindings/multi-file-defines.h | 66 +- tests/cpp-compiler/c-compile-error.c | 8 +- tests/cpp-compiler/c-compile-link-error.c | 6 +- .../c-compile-pass-through-shared-library.c | 25 +- .../c-compile-shared-library-link-error.c | 27 +- tests/cpp-compiler/c-compile-shared-library.c | 27 +- tests/cpp-compiler/c-compile.c | 6 +- tests/cpp-compiler/cpp-compile-shared-library.cpp | 18 +- tests/cpp-compiler/cpp-compile.cpp | 4 +- tests/cpp-compiler/simple-c-compile.c | 6 +- tests/front-end/parser-using-file-a.slang.h | 5 +- tests/front-end/pipeline-simple.slang.h | 37 +- tests/preprocessor/file-identity/b.h | 7 +- tests/preprocessor/file-identity/c.h | 7 +- tests/preprocessor/include-a.slang.h | 5 +- tests/preprocessor/include-multiple.slang.expected | 8 +- tests/preprocessor/output-includes.slang.expected | 8 +- tests/preprocessor/pragma-once-a.h | 5 +- tests/reflection/multi-file-defines.h | 64 +- tools/gfx-unit-test/buffer-barrier-test.cpp | 298 +- tools/gfx-unit-test/clear-texture-test.cpp | 141 +- tools/gfx-unit-test/compute-smoke.cpp | 202 +- tools/gfx-unit-test/compute-trivial.cpp | 169 +- tools/gfx-unit-test/copy-texture-tests.cpp | 1642 +- tools/gfx-unit-test/create-buffer-from-handle.cpp | 178 +- .../gfx-unit-test/existing-device-handle-test.cpp | 254 +- tools/gfx-unit-test/format-unit-tests.cpp | 2524 ++- .../get-buffer-resource-handle-test.cpp | 159 +- tools/gfx-unit-test/get-cmd-buffer-handle-test.cpp | 154 +- tools/gfx-unit-test/get-cmd-queue-handle-test.cpp | 125 +- .../get-supported-resource-states-test.cpp | 325 +- .../get-texture-resource-handle-test.cpp | 146 +- tools/gfx-unit-test/gfx-test-texture-util.cpp | 418 +- tools/gfx-unit-test/gfx-test-texture-util.h | 332 +- tools/gfx-unit-test/gfx-test-util.cpp | 618 +- tools/gfx-unit-test/gfx-test-util.h | 252 +- tools/gfx-unit-test/instanced-draw-tests.cpp | 990 +- tools/gfx-unit-test/link-time-constant.cpp | 285 +- tools/gfx-unit-test/link-time-default.cpp | 340 +- tools/gfx-unit-test/link-time-options.cpp | 274 +- tools/gfx-unit-test/link-time-type.cpp | 269 +- tools/gfx-unit-test/mutable-shader-object.cpp | 247 +- tools/gfx-unit-test/nested-parameter-block.cpp | 284 +- tools/gfx-unit-test/precompiled-module-2.cpp | 361 +- tools/gfx-unit-test/precompiled-module-cache.cpp | 336 +- tools/gfx-unit-test/precompiled-module.cpp | 273 +- tools/gfx-unit-test/ray-tracing-tests.cpp | 910 +- tools/gfx-unit-test/resolve-resource-tests.cpp | 619 +- tools/gfx-unit-test/root-mutable-shader-object.cpp | 208 +- tools/gfx-unit-test/root-shader-parameter.cpp | 244 +- tools/gfx-unit-test/sampler-array.cpp | 261 +- tools/gfx-unit-test/shader-cache-tests.cpp | 1857 +- tools/gfx-unit-test/shared-buffers-tests.cpp | 222 +- tools/gfx-unit-test/shared-textures-tests.cpp | 440 +- tools/gfx-unit-test/swap-chain-resize-test.cpp | 427 +- tools/gfx-unit-test/texture-types-tests.cpp | 1143 +- tools/gfx-unit-test/uint16-structured-buffer.cpp | 161 +- tools/gfx-util/shader-cursor.cpp | 41 +- tools/gfx-util/shader-cursor.h | 24 +- tools/gfx/apple/cocoa-util.h | 10 +- tools/gfx/command-encoder-com-forward.h | 301 +- tools/gfx/command-writer.h | 25 +- tools/gfx/cpu/cpu-base.h | 45 +- tools/gfx/cpu/cpu-buffer.cpp | 2 +- tools/gfx/cpu/cpu-buffer.h | 5 +- tools/gfx/cpu/cpu-device.cpp | 493 +- tools/gfx/cpu/cpu-device.h | 22 +- tools/gfx/cpu/cpu-helper-functions.cpp | 1 - tools/gfx/cpu/cpu-helper-functions.h | 1 - tools/gfx/cpu/cpu-pipeline-state.cpp | 22 +- tools/gfx/cpu/cpu-query.cpp | 4 +- tools/gfx/cpu/cpu-query.h | 4 +- tools/gfx/cpu/cpu-resource-views.cpp | 36 +- tools/gfx/cpu/cpu-resource-views.h | 28 +- tools/gfx/cpu/cpu-shader-object-layout.cpp | 64 +- tools/gfx/cpu/cpu-shader-object-layout.h | 20 +- tools/gfx/cpu/cpu-shader-object.cpp | 72 +- tools/gfx/cpu/cpu-shader-object.h | 28 +- tools/gfx/cpu/cpu-shader-program.h | 5 +- tools/gfx/cpu/cpu-texture.cpp | 48 +- tools/gfx/cpu/cpu-texture.h | 35 +- tools/gfx/cuda/cuda-base.h | 76 +- tools/gfx/cuda/cuda-buffer.cpp | 5 +- tools/gfx/cuda/cuda-buffer.h | 8 +- tools/gfx/cuda/cuda-command-buffer.cpp | 6 +- tools/gfx/cuda/cuda-command-buffer.h | 13 +- tools/gfx/cuda/cuda-command-encoder.cpp | 26 +- tools/gfx/cuda/cuda-command-encoder.h | 30 +- tools/gfx/cuda/cuda-command-queue.cpp | 29 +- tools/gfx/cuda/cuda-command-queue.h | 18 +- tools/gfx/cuda/cuda-device.cpp | 257 +- tools/gfx/cuda/cuda-device.h | 44 +- tools/gfx/cuda/cuda-helper-functions.cpp | 12 +- tools/gfx/cuda/cuda-helper-functions.h | 100 +- tools/gfx/cuda/cuda-query.cpp | 4 +- tools/gfx/cuda/cuda-query.h | 4 +- tools/gfx/cuda/cuda-resource-views.h | 1 - tools/gfx/cuda/cuda-shader-object-layout.cpp | 51 +- tools/gfx/cuda/cuda-shader-object-layout.h | 5 +- tools/gfx/cuda/cuda-shader-object.cpp | 37 +- tools/gfx/cuda/cuda-shader-object.h | 31 +- tools/gfx/cuda/cuda-shader-program.h | 1 - tools/gfx/cuda/cuda-texture.h | 7 +- tools/gfx/d3d/d3d-swapchain.h | 38 +- tools/gfx/d3d/d3d-util.cpp | 789 +- tools/gfx/d3d/d3d-util.h | 101 +- tools/gfx/d3d11/d3d11-base.h | 61 +- tools/gfx/d3d11/d3d11-buffer.cpp | 2 +- tools/gfx/d3d11/d3d11-buffer.h | 6 +- tools/gfx/d3d11/d3d11-device.cpp | 979 +- tools/gfx/d3d11/d3d11-device.h | 52 +- tools/gfx/d3d11/d3d11-helper-functions.cpp | 494 +- tools/gfx/d3d11/d3d11-helper-functions.h | 467 +- tools/gfx/d3d11/d3d11-pipeline-state.h | 12 +- tools/gfx/d3d11/d3d11-query.cpp | 21 +- tools/gfx/d3d11/d3d11-query.h | 23 +- tools/gfx/d3d11/d3d11-resource-views.h | 8 +- tools/gfx/d3d11/d3d11-scopeNVAPI.h | 5 +- tools/gfx/d3d11/d3d11-shader-object-layout.cpp | 60 +- tools/gfx/d3d11/d3d11-shader-object-layout.h | 107 +- tools/gfx/d3d11/d3d11-shader-object.cpp | 80 +- tools/gfx/d3d11/d3d11-shader-object.h | 115 +- tools/gfx/d3d11/d3d11-shader-program.cpp | 1 - tools/gfx/d3d11/d3d11-swap-chain.cpp | 5 +- tools/gfx/d3d11/d3d11-texture.h | 1 - tools/gfx/d3d11/d3d11-vertex-layout.h | 4 +- tools/gfx/d3d12/d3d12-base.h | 73 +- tools/gfx/d3d12/d3d12-buffer.cpp | 12 +- tools/gfx/d3d12/d3d12-buffer.h | 7 +- tools/gfx/d3d12/d3d12-command-buffer.cpp | 13 +- tools/gfx/d3d12/d3d12-command-buffer.h | 27 +- tools/gfx/d3d12/d3d12-command-encoder.cpp | 418 +- tools/gfx/d3d12/d3d12-command-encoder.h | 73 +- tools/gfx/d3d12/d3d12-command-queue.cpp | 19 +- tools/gfx/d3d12/d3d12-command-queue.h | 10 +- tools/gfx/d3d12/d3d12-descriptor-heap.cpp | 26 +- tools/gfx/d3d12/d3d12-descriptor-heap.h | 182 +- tools/gfx/d3d12/d3d12-device.cpp | 772 +- tools/gfx/d3d12/d3d12-device.h | 74 +- tools/gfx/d3d12/d3d12-fence.cpp | 6 +- tools/gfx/d3d12/d3d12-fence.h | 2 +- tools/gfx/d3d12/d3d12-helper-functions.cpp | 390 +- tools/gfx/d3d12/d3d12-helper-functions.h | 14 +- tools/gfx/d3d12/d3d12-pipeline-state-stream.h | 432 +- tools/gfx/d3d12/d3d12-pipeline-state.cpp | 129 +- tools/gfx/d3d12/d3d12-pipeline-state.h | 3 +- tools/gfx/d3d12/d3d12-posix-synchapi.cpp | 136 +- tools/gfx/d3d12/d3d12-posix-synchapi.h | 24 +- tools/gfx/d3d12/d3d12-query.cpp | 18 +- tools/gfx/d3d12/d3d12-query.h | 8 +- tools/gfx/d3d12/d3d12-resource-views.cpp | 177 +- tools/gfx/d3d12/d3d12-resource-views.h | 10 +- tools/gfx/d3d12/d3d12-resource.cpp | 123 +- tools/gfx/d3d12/d3d12-resource.h | 176 +- tools/gfx/d3d12/d3d12-sal-defs.h | 128 +- tools/gfx/d3d12/d3d12-sampler.cpp | 5 +- tools/gfx/d3d12/d3d12-shader-object-layout.cpp | 288 +- tools/gfx/d3d12/d3d12-shader-object-layout.h | 30 +- tools/gfx/d3d12/d3d12-shader-object.cpp | 226 +- tools/gfx/d3d12/d3d12-shader-object.h | 29 +- tools/gfx/d3d12/d3d12-shader-program.cpp | 3 +- tools/gfx/d3d12/d3d12-shader-program.h | 3 +- tools/gfx/d3d12/d3d12-shader-table.cpp | 10 +- tools/gfx/d3d12/d3d12-submitter.cpp | 22 +- tools/gfx/d3d12/d3d12-submitter.h | 25 +- tools/gfx/d3d12/d3d12-swap-chain.cpp | 16 +- tools/gfx/d3d12/d3d12-texture.cpp | 12 +- tools/gfx/d3d12/d3d12-texture.h | 2 +- tools/gfx/d3d12/d3d12-transient-heap.cpp | 10 +- tools/gfx/d3d12/d3d12-transient-heap.h | 10 +- tools/gfx/debug-layer/debug-base.h | 104 +- tools/gfx/debug-layer/debug-buffer.h | 5 +- tools/gfx/debug-layer/debug-command-buffer.cpp | 33 +- tools/gfx/debug-layer/debug-command-buffer.h | 9 +- tools/gfx/debug-layer/debug-command-encoder.cpp | 114 +- tools/gfx/debug-layer/debug-command-encoder.h | 82 +- tools/gfx/debug-layer/debug-command-queue.cpp | 22 +- tools/gfx/debug-layer/debug-command-queue.h | 11 +- tools/gfx/debug-layer/debug-device.cpp | 111 +- tools/gfx/debug-layer/debug-device.h | 56 +- tools/gfx/debug-layer/debug-fence.cpp | 5 +- tools/gfx/debug-layer/debug-fence.h | 4 +- tools/gfx/debug-layer/debug-framebuffer.h | 3 +- tools/gfx/debug-layer/debug-helper-functions.cpp | 39 +- tools/gfx/debug-layer/debug-helper-functions.h | 33 +- tools/gfx/debug-layer/debug-query.h | 3 +- tools/gfx/debug-layer/debug-resource-views.h | 5 +- tools/gfx/debug-layer/debug-sampler-state.h | 2 +- tools/gfx/debug-layer/debug-shader-object.cpp | 13 +- tools/gfx/debug-layer/debug-shader-object.h | 22 +- tools/gfx/debug-layer/debug-shader-program.h | 4 +- tools/gfx/debug-layer/debug-swap-chain.cpp | 3 +- tools/gfx/debug-layer/debug-swap-chain.h | 2 +- tools/gfx/debug-layer/debug-texture.cpp | 5 +- tools/gfx/debug-layer/debug-texture.h | 3 +- tools/gfx/debug-layer/debug-transient-heap.cpp | 6 +- tools/gfx/debug-layer/debug-transient-heap.h | 9 +- tools/gfx/flag-combiner.cpp | 3 +- tools/gfx/flag-combiner.h | 38 +- tools/gfx/immediate-renderer-base.cpp | 187 +- tools/gfx/immediate-renderer-base.h | 34 +- tools/gfx/metal/metal-api.cpp | 2 +- tools/gfx/metal/metal-base.h | 70 +- tools/gfx/metal/metal-buffer.cpp | 8 +- tools/gfx/metal/metal-buffer.h | 6 +- tools/gfx/metal/metal-command-buffer.cpp | 16 +- tools/gfx/metal/metal-command-buffer.h | 17 +- tools/gfx/metal/metal-command-encoder.cpp | 163 +- tools/gfx/metal/metal-command-encoder.h | 83 +- tools/gfx/metal/metal-command-queue.cpp | 33 +- tools/gfx/metal/metal-command-queue.h | 10 +- tools/gfx/metal/metal-device.cpp | 231 +- tools/gfx/metal/metal-device.h | 67 +- tools/gfx/metal/metal-fence.cpp | 5 +- tools/gfx/metal/metal-fence.h | 7 +- tools/gfx/metal/metal-framebuffer.cpp | 12 +- tools/gfx/metal/metal-helper-functions.cpp | 1 + tools/gfx/metal/metal-pipeline-state.cpp | 134 +- tools/gfx/metal/metal-query.cpp | 15 +- tools/gfx/metal/metal-query.h | 3 +- tools/gfx/metal/metal-render-pass.cpp | 44 +- tools/gfx/metal/metal-render-pass.h | 4 +- tools/gfx/metal/metal-resource-views.cpp | 17 +- tools/gfx/metal/metal-resource-views.h | 12 +- tools/gfx/metal/metal-sampler.cpp | 10 +- tools/gfx/metal/metal-sampler.h | 2 +- tools/gfx/metal/metal-shader-object-layout.cpp | 58 +- tools/gfx/metal/metal-shader-object-layout.h | 30 +- tools/gfx/metal/metal-shader-object.cpp | 196 +- tools/gfx/metal/metal-shader-object.h | 55 +- tools/gfx/metal/metal-shader-program.cpp | 17 +- tools/gfx/metal/metal-shader-program.h | 4 +- tools/gfx/metal/metal-swap-chain.cpp | 18 +- tools/gfx/metal/metal-swap-chain.h | 6 +- tools/gfx/metal/metal-texture.cpp | 9 +- tools/gfx/metal/metal-texture.h | 3 +- tools/gfx/metal/metal-transient-heap.cpp | 4 +- tools/gfx/metal/metal-transient-heap.h | 2 +- tools/gfx/metal/metal-util.cpp | 541 +- tools/gfx/metal/metal-util.h | 23 +- tools/gfx/metal/metal-vertex-layout.cpp | 18 +- tools/gfx/metal/metal-vertex-layout.h | 3 +- tools/gfx/mutable-shader-object.h | 668 +- tools/gfx/nvapi/nvapi-include.h | 27 +- tools/gfx/nvapi/nvapi-util.cpp | 9 +- tools/gfx/nvapi/nvapi-util.h | 11 +- tools/gfx/open-gl/render-gl.cpp | 868 +- tools/gfx/open-gl/render-gl.h | 5 +- tools/gfx/render.cpp | 172 +- tools/gfx/renderer-shared.cpp | 372 +- tools/gfx/renderer-shared.h | 402 +- tools/gfx/resource-desc-utils.cpp | 26 +- tools/gfx/resource-desc-utils.h | 22 +- tools/gfx/simple-render-pass-layout.h | 10 +- tools/gfx/simple-transient-resource-heap.h | 7 +- tools/gfx/slang-context.h | 108 +- tools/gfx/transient-resource-heap-base.h | 21 +- tools/gfx/vulkan/vk-api.cpp | 30 +- tools/gfx/vulkan/vk-api.h | 95 +- tools/gfx/vulkan/vk-base.h | 70 +- tools/gfx/vulkan/vk-buffer.cpp | 24 +- tools/gfx/vulkan/vk-buffer.h | 7 +- tools/gfx/vulkan/vk-command-buffer.cpp | 13 +- tools/gfx/vulkan/vk-command-buffer.h | 10 +- tools/gfx/vulkan/vk-command-encoder.cpp | 242 +- tools/gfx/vulkan/vk-command-encoder.h | 89 +- tools/gfx/vulkan/vk-command-queue.cpp | 26 +- tools/gfx/vulkan/vk-command-queue.h | 8 +- tools/gfx/vulkan/vk-descriptor-allocator.cpp | 11 +- tools/gfx/vulkan/vk-descriptor-allocator.h | 2 +- tools/gfx/vulkan/vk-device-queue.cpp | 19 +- tools/gfx/vulkan/vk-device-queue.h | 50 +- tools/gfx/vulkan/vk-device.cpp | 698 +- tools/gfx/vulkan/vk-device.h | 64 +- tools/gfx/vulkan/vk-fence.cpp | 32 +- tools/gfx/vulkan/vk-fence.h | 2 +- tools/gfx/vulkan/vk-framebuffer.cpp | 17 +- tools/gfx/vulkan/vk-helper-functions.cpp | 264 +- tools/gfx/vulkan/vk-helper-functions.h | 37 +- tools/gfx/vulkan/vk-module.cpp | 13 +- tools/gfx/vulkan/vk-module.h | 40 +- tools/gfx/vulkan/vk-pipeline-dump-layer.cpp | 280 +- tools/gfx/vulkan/vk-pipeline-dump-layer.h | 8 +- tools/gfx/vulkan/vk-pipeline-state.cpp | 89 +- tools/gfx/vulkan/vk-pipeline-state.h | 3 +- tools/gfx/vulkan/vk-query.cpp | 17 +- tools/gfx/vulkan/vk-query.h | 7 +- tools/gfx/vulkan/vk-render-pass.cpp | 10 +- tools/gfx/vulkan/vk-render-pass.h | 4 +- tools/gfx/vulkan/vk-resource-views.cpp | 10 +- tools/gfx/vulkan/vk-resource-views.h | 9 +- tools/gfx/vulkan/vk-sampler.cpp | 3 +- tools/gfx/vulkan/vk-shader-object-layout.cpp | 104 +- tools/gfx/vulkan/vk-shader-object-layout.h | 12 +- tools/gfx/vulkan/vk-shader-object.cpp | 72 +- tools/gfx/vulkan/vk-shader-object.h | 30 +- tools/gfx/vulkan/vk-shader-program.cpp | 13 +- tools/gfx/vulkan/vk-shader-program.h | 3 +- tools/gfx/vulkan/vk-shader-table.cpp | 16 +- tools/gfx/vulkan/vk-swap-chain.cpp | 61 +- tools/gfx/vulkan/vk-swap-chain.h | 6 +- tools/gfx/vulkan/vk-texture.cpp | 6 +- tools/gfx/vulkan/vk-texture.h | 2 +- tools/gfx/vulkan/vk-transient-heap.cpp | 16 +- tools/gfx/vulkan/vk-transient-heap.h | 2 +- tools/gfx/vulkan/vk-util.cpp | 624 +- tools/gfx/vulkan/vk-util.h | 76 +- tools/platform/gui.cpp | 91 +- tools/platform/gui.h | 15 +- tools/platform/linux/x11-key-code.cpp | 380 +- tools/platform/linux/x11-window.cpp | 223 +- tools/platform/model.cpp | 231 +- tools/platform/model.h | 33 +- tools/platform/performance-counter.h | 5 +- tools/platform/placeholder/placeholder-window.cpp | 17 +- tools/platform/platform-api.h | 24 +- tools/platform/vector-math.h | 7 +- tools/platform/window.h | 75 +- tools/platform/windows/win-window.cpp | 42 +- tools/render-test/diagnostic-defs.h | 14 +- tools/render-test/diagnostics.cpp | 13 +- tools/render-test/diagnostics.h | 10 +- tools/render-test/options.cpp | 97 +- tools/render-test/options.h | 36 +- tools/render-test/png-serialize-util.cpp | 7 +- tools/render-test/png-serialize-util.h | 12 +- tools/render-test/render-test-main.cpp | 584 +- tools/render-test/shader-input-layout.cpp | 2396 +-- tools/render-test/shader-input-layout.h | 75 +- tools/render-test/shader-renderer-util.cpp | 47 +- tools/render-test/shader-renderer-util.h | 18 +- tools/render-test/slang-support.cpp | 225 +- tools/render-test/slang-support.h | 66 +- .../capability-generator-main.cpp | 432 +- .../slang-capability-diagnostic-defs.h | 47 +- tools/slang-cpp-extractor/cpp-extractor-main.cpp | 118 +- tools/slang-cpp-extractor/diagnostic-defs.h | 30 +- tools/slang-cpp-extractor/diagnostics.cpp | 8 +- tools/slang-cpp-extractor/diagnostics.h | 10 +- tools/slang-cpp-extractor/file-util.cpp | 37 +- tools/slang-cpp-extractor/file-util.h | 23 +- tools/slang-cpp-extractor/identifier-lookup.cpp | 110 +- tools/slang-cpp-extractor/identifier-lookup.h | 57 +- tools/slang-cpp-extractor/macro-writer.cpp | 93 +- tools/slang-cpp-extractor/macro-writer.h | 26 +- tools/slang-cpp-extractor/node-tree.cpp | 53 +- tools/slang-cpp-extractor/node-tree.h | 56 +- tools/slang-cpp-extractor/node.cpp | 45 +- tools/slang-cpp-extractor/node.h | 236 +- tools/slang-cpp-extractor/options.cpp | 18 +- tools/slang-cpp-extractor/options.h | 42 +- tools/slang-cpp-extractor/parser.cpp | 399 +- tools/slang-cpp-extractor/parser.h | 45 +- tools/slang-cpp-extractor/unit-test.cpp | 98 +- tools/slang-cpp-extractor/unit-test.h | 5 +- tools/slang-embed/slang-embed.cpp | 78 +- tools/slang-generate/main.cpp | 289 +- .../lookup-generator-main.cpp | 30 +- tools/slang-profile/slang-profile-main.cpp | 7 +- .../slang-reflection-test-main.cpp | 480 +- tools/slang-replay/main.cpp | 32 +- .../spirv-embed-generator-main.cpp | 215 +- tools/slang-test/directory-util.cpp | 13 +- tools/slang-test/directory-util.h | 46 +- tools/slang-test/filecheck.h | 32 +- tools/slang-test/options.cpp | 30 +- tools/slang-test/options.h | 54 +- tools/slang-test/parse-diagnostic-util.cpp | 171 +- tools/slang-test/parse-diagnostic-util.h | 116 +- tools/slang-test/slang-test-main.cpp | 1390 +- tools/slang-test/slangc-tool.cpp | 20 +- tools/slang-test/slangc-tool.h | 10 +- tools/slang-test/test-context.cpp | 41 +- tools/slang-test/test-context.h | 59 +- tools/slang-test/test-reporter.cpp | 260 +- tools/slang-test/test-reporter.h | 90 +- tools/slang-unit-test/unit-test-byte-encode.cpp | 45 +- .../unit-test-com-host-callable.cpp | 134 +- .../unit-test-command-line-args.cpp | 50 +- tools/slang-unit-test/unit-test-compression.cpp | 24 +- tools/slang-unit-test/unit-test-crypto.cpp | 44 +- .../unit-test-decl-tree-reflection.cpp | 162 +- .../unit-test-default-matrix-layout.cpp | 32 +- tools/slang-unit-test/unit-test-fcpw-compile.cpp | 21 +- tools/slang-unit-test/unit-test-file-system.cpp | 880 +- .../unit-test-find-check-entrypoint.cpp | 32 +- .../unit-test-find-entrypoint-nested.cpp | 30 +- .../unit-test-find-type-by-name.cpp | 16 +- tools/slang-unit-test/unit-test-free-list.cpp | 11 +- .../unit-test-function-reflection.cpp | 53 +- .../unit-test-generic-interface-conformance.cpp | 45 +- .../slang-unit-test/unit-test-get-target-code.cpp | 16 +- .../unit-test-image-format-reflection.cpp | 30 +- tools/slang-unit-test/unit-test-io.cpp | 5 +- tools/slang-unit-test/unit-test-json-native.cpp | 36 +- tools/slang-unit-test/unit-test-json.cpp | 95 +- tools/slang-unit-test/unit-test-lock-file.cpp | 11 +- tools/slang-unit-test/unit-test-memory-arena.cpp | 47 +- .../slang-unit-test/unit-test-offset-container.cpp | 17 +- .../unit-test-parameter-usage-reflection.cpp | 30 +- tools/slang-unit-test/unit-test-path.cpp | 8 +- .../slang-unit-test/unit-test-persistent-cache.cpp | 145 +- tools/slang-unit-test/unit-test-process.cpp | 22 +- tools/slang-unit-test/unit-test-record-replay.cpp | 86 +- tools/slang-unit-test/unit-test-riff.cpp | 47 +- tools/slang-unit-test/unit-test-rtti.cpp | 32 +- tools/slang-unit-test/unit-test-short-list.cpp | 31 +- tools/slang-unit-test/unit-test-source-map.cpp | 32 +- tools/slang-unit-test/unit-test-string-escape.cpp | 115 +- tools/slang-unit-test/unit-test-string.cpp | 83 +- .../unit-test-translation-unit-import.cpp | 35 +- tools/slangd/main.cpp | 6 +- tools/test-process/test-process-main.cpp | 31 +- tools/test-server/test-server-diagnostic-defs.h | 6 +- tools/test-server/test-server-diagnostics.cpp | 8 +- tools/test-server/test-server-diagnostics.h | 15 +- tools/test-server/test-server-main.cpp | 154 +- tools/unit-test/slang-unit-test.cpp | 22 +- tools/unit-test/slang-unit-test.h | 58 +- tools/vk-pipeline-create/main.cpp | 46 +- 1187 files changed, 180770 insertions(+), 156956 deletions(-) diff --git a/examples/autodiff-texture/main.cpp b/examples/autodiff-texture/main.cpp index 8bffadd84..d09b7dbac 100644 --- a/examples/autodiff-texture/main.cpp +++ b/examples/autodiff-texture/main.cpp @@ -2,10 +2,10 @@ #include "gfx-util/shader-cursor.h" #include "slang-com-ptr.h" #include "slang-gfx.h" +#include "slang.h" #include "source/core/slang-basic.h" #include "tools/platform/vector-math.h" #include "tools/platform/window.h" -#include "slang.h" using namespace gfx; using namespace Slang; @@ -41,14 +41,18 @@ struct AutoDiffTexture : public WindowedAppBase } gfx::Result loadRenderProgram( - gfx::IDevice* device, const char* fileName, const char* fragmentShader, gfx::IShaderProgram** outProgram) + gfx::IDevice* device, + const char* fileName, + const char* fragmentShader, + gfx::IShaderProgram** outProgram) { ComPtr slangSession; slangSession = device->getSlangSession(); ComPtr diagnosticsBlob; Slang::String path = resourceBase.resolveResource(fileName); - slang::IModule* module = slangSession->loadModule(path.getBuffer(), diagnosticsBlob.writeRef()); + slang::IModule* module = + slangSession->loadModule(path.getBuffer(), diagnosticsBlob.writeRef()); diagnoseIfNeeded(diagnosticsBlob); if (!module) return SLANG_FAIL; @@ -91,14 +95,17 @@ struct AutoDiffTexture : public WindowedAppBase } gfx::Result loadComputeProgram( - gfx::IDevice* device, const char* fileName, gfx::IShaderProgram** outProgram) + gfx::IDevice* device, + const char* fileName, + gfx::IShaderProgram** outProgram) { ComPtr slangSession; slangSession = device->getSlangSession(); ComPtr diagnosticsBlob; Slang::String path = resourceBase.resolveResource(fileName); - slang::IModule* module = slangSession->loadModule(path.getBuffer(), diagnosticsBlob.writeRef()); + slang::IModule* module = + slangSession->loadModule(path.getBuffer(), diagnosticsBlob.writeRef()); diagnoseIfNeeded(diagnosticsBlob); if (!module) return SLANG_FAIL; @@ -174,7 +181,11 @@ struct AutoDiffTexture : public WindowedAppBase ClearValue kClearValue; bool resetLearntTexture = false; - ComPtr createRenderTargetTexture(gfx::Format format, int w, int h, int levels) + ComPtr createRenderTargetTexture( + gfx::Format format, + int w, + int h, + int levels) { gfx::ITextureResource::Desc textureDesc = {}; textureDesc.allowedStates.add(ResourceState::ShaderResource); @@ -239,7 +250,8 @@ struct AutoDiffTexture : public WindowedAppBase return gDevice->createTextureView(tex, rtvDesc); } ComPtr createRenderPipelineState( - IInputLayout* inputLayout, IShaderProgram* program) + IInputLayout* inputLayout, + IShaderProgram* program) { GraphicsPipelineStateDesc desc; desc.inputLayout = inputLayout; @@ -269,7 +281,7 @@ struct AutoDiffTexture : public WindowedAppBase desc.subresourceRange.layerCount = 1; desc.subresourceRange.mipLevel = level; desc.subresourceRange.baseArrayLayer = 0; - return gDevice->createTextureView(texture,desc); + return gDevice->createTextureView(texture, desc); } Slang::Result initialize() { @@ -320,20 +332,29 @@ struct AutoDiffTexture : public WindowedAppBase { ComPtr shaderProgram; - SLANG_RETURN_ON_FAIL( - loadRenderProgram(gDevice, "train.slang", "fragmentMain", shaderProgram.writeRef())); + SLANG_RETURN_ON_FAIL(loadRenderProgram( + gDevice, + "train.slang", + "fragmentMain", + shaderProgram.writeRef())); gRefPipelineState = createRenderPipelineState(inputLayout, shaderProgram); } { ComPtr shaderProgram; - SLANG_RETURN_ON_FAIL( - loadRenderProgram(gDevice, "train.slang", "diffFragmentMain", shaderProgram.writeRef())); + SLANG_RETURN_ON_FAIL(loadRenderProgram( + gDevice, + "train.slang", + "diffFragmentMain", + shaderProgram.writeRef())); gIterPipelineState = createRenderPipelineState(inputLayout, shaderProgram); } { ComPtr shaderProgram; - SLANG_RETURN_ON_FAIL( - loadRenderProgram(gDevice, "draw-quad.slang", "fragmentMain", shaderProgram.writeRef())); + SLANG_RETURN_ON_FAIL(loadRenderProgram( + gDevice, + "draw-quad.slang", + "fragmentMain", + shaderProgram.writeRef())); gDrawQuadPipelineState = createRenderPipelineState(inputLayout, shaderProgram); } { @@ -344,17 +365,20 @@ struct AutoDiffTexture : public WindowedAppBase } { ComPtr shaderProgram; - SLANG_RETURN_ON_FAIL(loadComputeProgram(gDevice, "convert.slang", shaderProgram.writeRef())); + SLANG_RETURN_ON_FAIL( + loadComputeProgram(gDevice, "convert.slang", shaderProgram.writeRef())); gConvertPipelineState = createComputePipelineState(shaderProgram); } { ComPtr shaderProgram; - SLANG_RETURN_ON_FAIL(loadComputeProgram(gDevice, "buildmip.slang", shaderProgram.writeRef())); + SLANG_RETURN_ON_FAIL( + loadComputeProgram(gDevice, "buildmip.slang", shaderProgram.writeRef())); gBuildMipPipelineState = createComputePipelineState(shaderProgram); } { ComPtr shaderProgram; - SLANG_RETURN_ON_FAIL(loadComputeProgram(gDevice, "learnmip.slang", shaderProgram.writeRef())); + SLANG_RETURN_ON_FAIL( + loadComputeProgram(gDevice, "learnmip.slang", shaderProgram.writeRef())); gLearnMipPipelineState = createComputePipelineState(shaderProgram); } @@ -394,7 +418,7 @@ struct AutoDiffTexture : public WindowedAppBase gDiffTextureUAVs.add(createUAV(gDiffTexture, i)); gfx::ISamplerState::Desc samplerDesc = {}; - //samplerDesc.maxLOD = 0.0f; + // samplerDesc.maxLOD = 0.0f; gSampler = gDevice->createSamplerState(samplerDesc); gDepthTexture = createDepthTexture(); @@ -404,7 +428,8 @@ struct AutoDiffTexture : public WindowedAppBase gRefImageRTV = createRTV(gRefImage, Format::R8G8B8A8_UNORM); gRefImageSRV = createSRV(gRefImage); - gIterImage = createRenderTargetTexture(Format::R8G8B8A8_UNORM, windowWidth, windowHeight, 1); + gIterImage = + createRenderTargetTexture(Format::R8G8B8A8_UNORM, windowWidth, windowHeight, 1); gIterImageRTV = createRTV(gIterImage, Format::R8G8B8A8_UNORM); gIterImageSRV = createSRV(gIterImage); @@ -414,17 +439,38 @@ struct AutoDiffTexture : public WindowedAppBase { ComPtr commandBuffer = gTransientHeaps[0]->createCommandBuffer(); auto encoder = commandBuffer->encodeResourceCommands(); - encoder->textureBarrier(gLearningTexture, ResourceState::RenderTarget, ResourceState::UnorderedAccess); - encoder->textureBarrier(gDiffTexture, ResourceState::RenderTarget, ResourceState::UnorderedAccess); - encoder->textureBarrier(gRefImage, ResourceState::RenderTarget, ResourceState::ShaderResource); - encoder->textureBarrier(gIterImage, ResourceState::RenderTarget, ResourceState::ShaderResource); + encoder->textureBarrier( + gLearningTexture, + ResourceState::RenderTarget, + ResourceState::UnorderedAccess); + encoder->textureBarrier( + gDiffTexture, + ResourceState::RenderTarget, + ResourceState::UnorderedAccess); + encoder->textureBarrier( + gRefImage, + ResourceState::RenderTarget, + ResourceState::ShaderResource); + encoder->textureBarrier( + gIterImage, + ResourceState::RenderTarget, + ResourceState::ShaderResource); for (int i = 0; i < gLearningTextureUAVs.getCount(); i++) { ClearValue clearValue = {}; - encoder->clearResourceView(gLearningTextureUAVs[i], &clearValue, ClearResourceViewFlags::None); - encoder->clearResourceView(gDiffTextureUAVs[i], &clearValue, ClearResourceViewFlags::None); + encoder->clearResourceView( + gLearningTextureUAVs[i], + &clearValue, + ClearResourceViewFlags::None); + encoder->clearResourceView( + gDiffTextureUAVs[i], + &clearValue, + ClearResourceViewFlags::None); } - encoder->textureBarrier(gLearningTexture, ResourceState::UnorderedAccess, ResourceState::ShaderResource); + encoder->textureBarrier( + gLearningTexture, + ResourceState::UnorderedAccess, + ResourceState::ShaderResource); encoder->endEncoding(); commandBuffer->close(); @@ -453,7 +499,10 @@ struct AutoDiffTexture : public WindowedAppBase float rotX = (rand() / (float)RAND_MAX) * 0.3f; float rotY = (rand() / (float)RAND_MAX) * 0.2f; glm::mat4x4 matProj = glm::perspectiveRH_ZO( - glm::radians(60.0f), (float)windowWidth / (float)windowHeight, 0.1f, 1000.0f); + glm::radians(60.0f), + (float)windowWidth / (float)windowHeight, + 0.1f, + 1000.0f); auto identity = glm::mat4(1.0f); auto translate = glm::translate( identity, @@ -468,9 +517,11 @@ struct AutoDiffTexture : public WindowedAppBase return transformMatrix; } - template + template void renderImage( - int transientHeapIndex, IFramebuffer* fb, const SetupPipelineFunc& setupPipeline) + int transientHeapIndex, + IFramebuffer* fb, + const SetupPipelineFunc& setupPipeline) { ComPtr commandBuffer = gTransientHeaps[transientHeapIndex]->createCommandBuffer(); @@ -496,9 +547,13 @@ struct AutoDiffTexture : public WindowedAppBase void renderReferenceImage(int transientHeapIndex, glm::mat4x4 transformMatrix) { { - ComPtr commandBuffer = gTransientHeaps[transientHeapIndex]->createCommandBuffer(); + ComPtr commandBuffer = + gTransientHeaps[transientHeapIndex]->createCommandBuffer(); auto encoder = commandBuffer->encodeResourceCommands(); - encoder->textureBarrier(gRefImage, ResourceState::ShaderResource, ResourceState::RenderTarget); + encoder->textureBarrier( + gRefImage, + ResourceState::ShaderResource, + ResourceState::RenderTarget); encoder->endEncoding(); commandBuffer->close(); gQueue->executeCommandBuffer(commandBuffer); @@ -512,12 +567,16 @@ struct AutoDiffTexture : public WindowedAppBase auto rootObject = encoder->bindPipeline(gRefPipelineState); ShaderCursor rootCursor(rootObject); rootCursor["Uniforms"]["modelViewProjection"].setData( - &transformMatrix, sizeof(float) * 16); + &transformMatrix, + sizeof(float) * 16); rootCursor["Uniforms"]["bwdTexture"]["texture"].setResource(gTexView); rootCursor["Uniforms"]["sampler"].setSampler(gSampler); - rootCursor["Uniforms"]["mipOffset"].setData(mipMapOffset.getBuffer(), sizeof(uint32_t) * mipMapOffset.getCount()); + rootCursor["Uniforms"]["mipOffset"].setData( + mipMapOffset.getBuffer(), + sizeof(uint32_t) * mipMapOffset.getCount()); rootCursor["Uniforms"]["texRef"].setResource(gTexView); - rootCursor["Uniforms"]["bwdTexture"]["accumulateBuffer"].setResource(gAccumulateBufferView); + rootCursor["Uniforms"]["bwdTexture"]["accumulateBuffer"].setResource( + gAccumulateBufferView); }); } @@ -527,25 +586,52 @@ struct AutoDiffTexture : public WindowedAppBase frameCount++; auto transformMatrix = getTransformMatrix(); renderReferenceImage(frameBufferIndex, transformMatrix); - + // Barriers. { ComPtr commandBuffer = gTransientHeaps[frameBufferIndex]->createCommandBuffer(); auto resEncoder = commandBuffer->encodeResourceCommands(); ClearValue clearValue = {}; - resEncoder->bufferBarrier(gAccumulateBuffer, ResourceState::Undefined, ResourceState::UnorderedAccess); - resEncoder->bufferBarrier(gReconstructBuffer, ResourceState::Undefined, ResourceState::UnorderedAccess); - resEncoder->textureBarrier(gRefImage, ResourceState::Present, ResourceState::ShaderResource); - resEncoder->textureBarrier(gIterImage, ResourceState::ShaderResource, ResourceState::RenderTarget); - resEncoder->clearResourceView(gAccumulateBufferView, &clearValue, ClearResourceViewFlags::None); - resEncoder->clearResourceView(gReconstructBufferView, &clearValue, ClearResourceViewFlags::None); + resEncoder->bufferBarrier( + gAccumulateBuffer, + ResourceState::Undefined, + ResourceState::UnorderedAccess); + resEncoder->bufferBarrier( + gReconstructBuffer, + ResourceState::Undefined, + ResourceState::UnorderedAccess); + resEncoder->textureBarrier( + gRefImage, + ResourceState::Present, + ResourceState::ShaderResource); + resEncoder->textureBarrier( + gIterImage, + ResourceState::ShaderResource, + ResourceState::RenderTarget); + resEncoder->clearResourceView( + gAccumulateBufferView, + &clearValue, + ClearResourceViewFlags::None); + resEncoder->clearResourceView( + gReconstructBufferView, + &clearValue, + ClearResourceViewFlags::None); if (resetLearntTexture) { - resEncoder->textureBarrier(gLearningTexture, ResourceState::ShaderResource, ResourceState::UnorderedAccess); - for (Index i =0; i clearResourceView(gLearningTextureUAVs[i], &clearValue, ClearResourceViewFlags::None); - resEncoder->textureBarrier(gLearningTexture, ResourceState::UnorderedAccess, ResourceState::ShaderResource); + resEncoder->textureBarrier( + gLearningTexture, + ResourceState::ShaderResource, + ResourceState::UnorderedAccess); + for (Index i = 0; i < gLearningTextureUAVs.getCount(); i++) + resEncoder->clearResourceView( + gLearningTextureUAVs[i], + &clearValue, + ClearResourceViewFlags::None); + resEncoder->textureBarrier( + gLearningTexture, + ResourceState::UnorderedAccess, + ResourceState::ShaderResource); resetLearntTexture = false; } resEncoder->endEncoding(); @@ -561,16 +647,19 @@ struct AutoDiffTexture : public WindowedAppBase { auto rootObject = encoder->bindPipeline(gIterPipelineState); ShaderCursor rootCursor(rootObject); - + rootCursor["Uniforms"]["modelViewProjection"].setData( - &transformMatrix, sizeof(float) * 16); + &transformMatrix, + sizeof(float) * 16); rootCursor["Uniforms"]["bwdTexture"]["texture"].setResource(gLearningTextureSRV); rootCursor["Uniforms"]["sampler"].setSampler(gSampler); - rootCursor["Uniforms"]["mipOffset"].setData(mipMapOffset.getBuffer(), sizeof(uint32_t) * mipMapOffset.getCount()); + rootCursor["Uniforms"]["mipOffset"].setData( + mipMapOffset.getBuffer(), + sizeof(uint32_t) * mipMapOffset.getCount()); rootCursor["Uniforms"]["texRef"].setResource(gRefImageSRV); - rootCursor["Uniforms"]["bwdTexture"]["accumulateBuffer"].setResource(gAccumulateBufferView); + rootCursor["Uniforms"]["bwdTexture"]["accumulateBuffer"].setResource( + gAccumulateBufferView); rootCursor["Uniforms"]["bwdTexture"]["minLOD"].setData(5.0); - }); // Propagete gradients through mip map layers from top (lowest res) to bottom (highest res). @@ -578,12 +667,17 @@ struct AutoDiffTexture : public WindowedAppBase ComPtr commandBuffer = gTransientHeaps[frameBufferIndex]->createCommandBuffer(); auto encoder = commandBuffer->encodeComputeCommands(); - encoder->textureBarrier(gLearningTexture, ResourceState::ShaderResource, ResourceState::UnorderedAccess); + encoder->textureBarrier( + gLearningTexture, + ResourceState::ShaderResource, + ResourceState::UnorderedAccess); auto rootObject = encoder->bindPipeline(gReconstructPipelineState); for (int i = (int)mipMapOffset.getCount() - 2; i >= 0; i--) { ShaderCursor rootCursor(rootObject); - rootCursor["Uniforms"]["mipOffset"].setData(mipMapOffset.getBuffer(), sizeof(uint32_t) * mipMapOffset.getCount()); + rootCursor["Uniforms"]["mipOffset"].setData( + mipMapOffset.getBuffer(), + sizeof(uint32_t) * mipMapOffset.getCount()); rootCursor["Uniforms"]["dstLayer"].setData(i); rootCursor["Uniforms"]["layerCount"].setData(mipMapOffset.getCount() - 1); rootCursor["Uniforms"]["width"].setData(textureWidth); @@ -591,22 +685,31 @@ struct AutoDiffTexture : public WindowedAppBase rootCursor["Uniforms"]["accumulateBuffer"].setResource(gAccumulateBufferView); rootCursor["Uniforms"]["dstBuffer"].setResource(gReconstructBufferView); encoder->dispatchCompute( - ((textureWidth >> i) + 15) / 16, ((textureHeight >> i) + 15) / 16, 1); - encoder->bufferBarrier(gReconstructBuffer, ResourceState::UnorderedAccess, ResourceState::UnorderedAccess); + ((textureWidth >> i) + 15) / 16, + ((textureHeight >> i) + 15) / 16, + 1); + encoder->bufferBarrier( + gReconstructBuffer, + ResourceState::UnorderedAccess, + ResourceState::UnorderedAccess); } // Convert bottom layer mip from buffer to texture. rootObject = encoder->bindPipeline(gConvertPipelineState); ShaderCursor rootCursor(rootObject); - rootCursor["Uniforms"]["mipOffset"].setData(mipMapOffset.getBuffer(), sizeof(uint32_t) * mipMapOffset.getCount()); + rootCursor["Uniforms"]["mipOffset"].setData( + mipMapOffset.getBuffer(), + sizeof(uint32_t) * mipMapOffset.getCount()); rootCursor["Uniforms"]["dstLayer"].setData(0); rootCursor["Uniforms"]["width"].setData(textureWidth); rootCursor["Uniforms"]["height"].setData(textureHeight); rootCursor["Uniforms"]["srcBuffer"].setResource(gReconstructBufferView); rootCursor["Uniforms"]["dstTexture"].setResource(gDiffTextureUAVs[0]); - encoder->dispatchCompute( - (textureWidth + 15) / 16, (textureHeight + 15) / 16, 1); - encoder->textureBarrier(gDiffTexture, ResourceState::UnorderedAccess, ResourceState::UnorderedAccess); + encoder->dispatchCompute((textureWidth + 15) / 16, (textureHeight + 15) / 16, 1); + encoder->textureBarrier( + gDiffTexture, + ResourceState::UnorderedAccess, + ResourceState::UnorderedAccess); // Build higher level mip map layers. rootObject = encoder->bindPipeline(gBuildMipPipelineState); @@ -615,11 +718,16 @@ struct AutoDiffTexture : public WindowedAppBase ShaderCursor rootCursor(rootObject); rootCursor["Uniforms"]["dstWidth"].setData(textureWidth >> i); rootCursor["Uniforms"]["dstHeight"].setData(textureHeight >> i); - rootCursor["Uniforms"]["srcTexture"].setResource(gDiffTextureUAVs[i-1]); + rootCursor["Uniforms"]["srcTexture"].setResource(gDiffTextureUAVs[i - 1]); rootCursor["Uniforms"]["dstTexture"].setResource(gDiffTextureUAVs[i]); encoder->dispatchCompute( - ((textureWidth >> i) + 15) / 16, ((textureHeight >> i) + 15) / 16, 1); - encoder->textureBarrier(gDiffTexture, ResourceState::UnorderedAccess, ResourceState::UnorderedAccess); + ((textureWidth >> i) + 15) / 16, + ((textureHeight >> i) + 15) / 16, + 1); + encoder->textureBarrier( + gDiffTexture, + ResourceState::UnorderedAccess, + ResourceState::UnorderedAccess); } // Accumulate gradients to learnt texture. @@ -633,10 +741,18 @@ struct AutoDiffTexture : public WindowedAppBase rootCursor["Uniforms"]["srcTexture"].setResource(gDiffTextureUAVs[i]); rootCursor["Uniforms"]["dstTexture"].setResource(gLearningTextureUAVs[i]); encoder->dispatchCompute( - ((textureWidth >> i) + 15) / 16, ((textureHeight >> i) + 15) / 16, 1); + ((textureWidth >> i) + 15) / 16, + ((textureHeight >> i) + 15) / 16, + 1); } - encoder->textureBarrier(gLearningTexture, ResourceState::UnorderedAccess, ResourceState::ShaderResource); - encoder->textureBarrier(gIterImage, ResourceState::Present, ResourceState::ShaderResource); + encoder->textureBarrier( + gLearningTexture, + ResourceState::UnorderedAccess, + ResourceState::ShaderResource); + encoder->textureBarrier( + gIterImage, + ResourceState::Present, + ResourceState::ShaderResource); encoder->endEncoding(); commandBuffer->close(); @@ -647,12 +763,25 @@ struct AutoDiffTexture : public WindowedAppBase { ComPtr commandBuffer = gTransientHeaps[frameBufferIndex]->createCommandBuffer(); - auto renderEncoder = commandBuffer->encodeRenderCommands(gRenderPass, gFramebuffers[frameBufferIndex]); + auto renderEncoder = + commandBuffer->encodeRenderCommands(gRenderPass, gFramebuffers[frameBufferIndex]); drawTexturedQuad(renderEncoder, 0, 0, textureWidth, textureHeight, gLearningTextureSRV); int refImageWidth = windowWidth - textureWidth - 10; int refImageHeight = refImageWidth * windowHeight / windowWidth; - drawTexturedQuad(renderEncoder, textureWidth + 10, 0, refImageWidth, refImageHeight, gRefImageSRV); - drawTexturedQuad(renderEncoder, textureWidth + 10, refImageHeight + 10, refImageWidth, refImageHeight, gIterImageSRV); + drawTexturedQuad( + renderEncoder, + textureWidth + 10, + 0, + refImageWidth, + refImageHeight, + gRefImageSRV); + drawTexturedQuad( + renderEncoder, + textureWidth + 10, + refImageHeight + 10, + refImageWidth, + refImageHeight, + gIterImageSRV); renderEncoder->endEncoding(); commandBuffer->close(); gQueue->executeCommandBuffer(commandBuffer); @@ -664,7 +793,13 @@ struct AutoDiffTexture : public WindowedAppBase } } - void drawTexturedQuad(IRenderCommandEncoder* renderEncoder, int x, int y, int w, int h, IResourceView* srv) + void drawTexturedQuad( + IRenderCommandEncoder* renderEncoder, + int x, + int y, + int w, + int h, + IResourceView* srv) { gfx::Viewport viewport = {}; viewport.maxZ = 1.0f; @@ -686,7 +821,6 @@ struct AutoDiffTexture : public WindowedAppBase renderEncoder->setPrimitiveTopology(PrimitiveTopology::TriangleStrip); renderEncoder->draw(4); } - }; PLATFORM_UI_MAIN(innerMain) diff --git a/examples/cpu-com-example/main.cpp b/examples/cpu-com-example/main.cpp index 62a01d17f..382b3cacd 100644 --- a/examples/cpu-com-example/main.cpp +++ b/examples/cpu-com-example/main.cpp @@ -1,11 +1,10 @@ // main.cpp -#include - +#include "slang-com-helper.h" +#include "slang-com-ptr.h" #include "slang.h" -#include "slang-com-ptr.h" -#include "slang-com-helper.h" +#include // This includes a useful small function for setting up the prelude (described more further below). #include "../../source/core/slang-test-tool-util.h" @@ -17,9 +16,9 @@ using namespace Slang; static const ExampleResources resourceBase("cpu-com-example"); -// For the moment we have to explicitly write the Slang COM interface in C++ code. It *MUST* match +// For the moment we have to explicitly write the Slang COM interface in C++ code. It *MUST* match // the interface in the slang source -// As it stands all interfaces need to derive from ISlangUnknown (or IUnknown). +// As it stands all interfaces need to derive from ISlangUnknown (or IUnknown). class IDoThings : public ISlangUnknown { public: @@ -43,19 +42,33 @@ class DoThings : public IDoThings { public: // We don't need queryInterface for this impl, or ref counting - virtual SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE { return SLANG_E_NOT_IMPLEMENTED; } - virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } - virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE + { + return SLANG_E_NOT_IMPLEMENTED; + } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } + virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } // IDoThings - virtual SLANG_NO_THROW int SLANG_MCALL doThing(int a, int b) SLANG_OVERRIDE { return a + b + 1; } - virtual SLANG_NO_THROW int SLANG_MCALL calcHash(const char* in) SLANG_OVERRIDE { return (int)_calcHash(in); } - virtual SLANG_NO_THROW void SLANG_MCALL printMessage(const char* in) SLANG_OVERRIDE { printf("%s\n", in); } + virtual SLANG_NO_THROW int SLANG_MCALL doThing(int a, int b) SLANG_OVERRIDE + { + return a + b + 1; + } + virtual SLANG_NO_THROW int SLANG_MCALL calcHash(const char* in) SLANG_OVERRIDE + { + return (int)_calcHash(in); + } + virtual SLANG_NO_THROW void SLANG_MCALL printMessage(const char* in) SLANG_OVERRIDE + { + printf("%s\n", in); + } }; static SlangResult _innerMain(int argc, char** argv) { - // NOTE! This example only works if `slang-llvm` or a C++ compiler that Slang supports is available. + // NOTE! This example only works if `slang-llvm` or a C++ compiler that Slang supports is + // available. // Create the session ComPtr slangSession; @@ -72,16 +85,17 @@ static SlangResult _innerMain(int argc, char** argv) SLANG_ALLOW_DEPRECATED_END // We want to compile to 'HOST_CALLABLE' here such that we can execute the Slang code. - // - // Note that it is possible to use HOST_HOST_CALLABLE, but this currently only works with 'regular' C++ compilers - // not with `slang-llvm`. + // + // Note that it is possible to use HOST_HOST_CALLABLE, but this currently only works with + // 'regular' C++ compilers not with `slang-llvm`. const int targetIndex = request->addCodeGenTarget(SLANG_SHADER_HOST_CALLABLE); // Set the target flag to indicate that we want to compile all into a library. request->setTargetFlags(targetIndex, SLANG_TARGET_FLAG_GENERATE_WHOLE_PROGRAM); // Add the translation unit - const int translationUnitIndex = request->addTranslationUnit(SLANG_SOURCE_LANGUAGE_SLANG, nullptr); + const int translationUnitIndex = + request->addTranslationUnit(SLANG_SOURCE_LANGUAGE_SLANG, nullptr); // Set the source file for the translation unit Slang::String path = resourceBase.resolveResource("shader.slang"); @@ -93,13 +107,13 @@ static SlangResult _innerMain(int argc, char** argv) // compiler may have produced "diagnostic" output such as warnings. // We will go ahead and print that output here. // - if(auto diagnostics = request->getDiagnosticOutput()) + if (auto diagnostics = request->getDiagnosticOutput()) { printf("%s", diagnostics); } - // Get the 'shared library' (note that this doesn't necessarily have to be implemented as a shared library - // it's just an interface to executable code). + // Get the 'shared library' (note that this doesn't necessarily have to be implemented as a + // shared library it's just an interface to executable code). ComPtr sharedLibrary; SLANG_RETURN_ON_FAIL(request->getTargetHostCallable(0, sharedLibrary.writeRef())); diff --git a/examples/cpu-hello-world/main.cpp b/examples/cpu-hello-world/main.cpp index 059efc8d3..60a24fa8c 100644 --- a/examples/cpu-hello-world/main.cpp +++ b/examples/cpu-hello-world/main.cpp @@ -3,7 +3,7 @@ #include // This file implements an extremely simple example of loading and -// executing a Slang shader program on the CPU. +// executing a Slang shader program on the CPU. // // More information about generation C++ or CPU code can be found in docs/cpu-target.md // @@ -20,7 +20,7 @@ // Allows use of ComPtr - which we can use to scope any 'com-like' pointers easily #include "slang-com-ptr.h" -// Provides macros for handling SlangResult values easily +// Provides macros for handling SlangResult values easily #include "slang-com-helper.h" // This includes a useful small function for setting up the prelude (described more further below). @@ -34,10 +34,10 @@ using namespace Slang; // Slang source is converted into C++ code which is compiled by a backend compiler. // That process uses a 'prelude' which defines types and functions that are needed // for everything else to work. -// +// // We include the prelude here, so we can directly use the types as were used by the // compiled code. It is not necessary to include the prelude, as long as memory is -// laid out in the manner that the generated slang code expects. +// laid out in the manner that the generated slang code expects. #define SLANG_PRELUDE_NAMESPACE CPPPrelude #include "../../prelude/slang-cpp-types.h" @@ -75,11 +75,13 @@ static SlangResult _innerMain(int argc, char** argv) // // Most downstream C++ compilers work on files. In that case slang may generate temporary // files that contain the generated code. Typically the generated files will not be in the - // same directory as the original source so handling includes becomes awkward. The mechanism used here - // is for the prelude code to be an *absolute* path to the 'slang-cpp-prelude.h' - which means - // this will work wherever the generated code is, and allows accessing other files via relative paths. + // same directory as the original source so handling includes becomes awkward. The mechanism + // used here is for the prelude code to be an *absolute* path to the 'slang-cpp-prelude.h' - + // which means this will work wherever the generated code is, and allows accessing other files + // via relative paths. // - // Look at the source to TestToolUtil::setSessionDefaultPreludeFromExePath to see what's involed. + // Look at the source to TestToolUtil::setSessionDefaultPreludeFromExePath to see what's + // involed. TestToolUtil::setSessionDefaultPreludeFromExePath(argv[0], slangSession); slang::SessionDesc sessionDesc = {}; @@ -122,13 +124,16 @@ static SlangResult _innerMain(int argc, char** argv) SLANG_RETURN_ON_FAIL(result); } - // Get the 'shared library' (note that this doesn't necessarily have to be implemented as a shared library - // it's just an interface to executable code). + // Get the 'shared library' (note that this doesn't necessarily have to be implemented as a + // shared library it's just an interface to executable code). ComPtr sharedLibrary; { ComPtr diagnosticsBlob; SlangResult result = composedProgram->getEntryPointHostCallable( - 0, 0, sharedLibrary.writeRef(), diagnosticsBlob.writeRef()); + 0, + 0, + sharedLibrary.writeRef(), + diagnosticsBlob.writeRef()); diagnoseIfNeeded(diagnosticsBlob); SLANG_RETURN_ON_FAIL(result); if (testBase.isTestMode()) @@ -137,55 +142,58 @@ static SlangResult _innerMain(int argc, char** argv) } } // Once we have the sharedLibrary, we no longer need the request - // unless we want to use reflection, to for example workout how 'UniformState' and 'UniformEntryPointParams' are laid out - // at runtime. We don't do that here - as we hard code the structures. + // unless we want to use reflection, to for example workout how 'UniformState' and + // 'UniformEntryPointParams' are laid out at runtime. We don't do that here - as we hard code + // the structures. // Get the function we are going to execute const char entryPointName[] = "computeMain"; - CPPPrelude::ComputeFunc func = (CPPPrelude::ComputeFunc)sharedLibrary->findFuncByName(entryPointName); + CPPPrelude::ComputeFunc func = + (CPPPrelude::ComputeFunc)sharedLibrary->findFuncByName(entryPointName); if (!func) { return SLANG_FAIL; } // Define the uniform state structure that is *specific* to our shader defined in shader.slang - // That the layout of the structure can be determined through reflection, or can be inferred from - // the original slang source. Look at the documentation in docs/cpu-target.md which describes - // how different resources map. - // The order of the resources is in the order that they are defined in the source. + // That the layout of the structure can be determined through reflection, or can be inferred + // from the original slang source. Look at the documentation in docs/cpu-target.md which + // describes how different resources map. The order of the resources is in the order that they + // are defined in the source. struct UniformState { CPPPrelude::RWStructuredBuffer ioBuffer; }; - // the uniformState will be passed as a pointer to the CPU code + // the uniformState will be passed as a pointer to the CPU code UniformState uniformState; // The contents of the buffer are modified, so we'll copy it - const float startBufferContents[] = { 2.0f, -10.0f, -3.0f, 5.0f }; + const float startBufferContents[] = {2.0f, -10.0f, -3.0f, 5.0f}; float bufferContents[SLANG_COUNT_OF(startBufferContents)]; memcpy(bufferContents, startBufferContents, sizeof(startBufferContents)); // Set up the ioBuffer such that it uses bufferContents. It is important to set the .count - // such that bounds checking can be performed in the kernel. + // such that bounds checking can be performed in the kernel. uniformState.ioBuffer.data = bufferContents; uniformState.ioBuffer.count = SLANG_COUNT_OF(bufferContents); - // In shader.slang, then entry point is attributed with `[numthreads(4, 1, 1)]` meaning each group - // consists of 4 'thread' in x. Our input buffer is 4 wide, and we index the input array via `SV_DispatchThreadID` - // so we only need to run a single group to execute over all of the 4 elements here. - // The group range from { 0, 0, 0 } -> { 1, 1, 1 } means it will execute over the single group { 0, 0, 0 }. + // In shader.slang, then entry point is attributed with `[numthreads(4, 1, 1)]` meaning each + // group consists of 4 'thread' in x. Our input buffer is 4 wide, and we index the input array + // via `SV_DispatchThreadID` so we only need to run a single group to execute over all of the 4 + // elements here. The group range from { 0, 0, 0 } -> { 1, 1, 1 } means it will execute over the + // single group { 0, 0, 0 }. - const CPPPrelude::uint3 startGroupID = { 0, 0, 0}; - const CPPPrelude::uint3 endGroupID = { 1, 1, 1 }; + const CPPPrelude::uint3 startGroupID = {0, 0, 0}; + const CPPPrelude::uint3 endGroupID = {1, 1, 1}; CPPPrelude::ComputeVaryingInput varyingInput; varyingInput.startGroupID = startGroupID; varyingInput.endGroupID = endGroupID; // We don't have any entry point parameters so that's passed as NULL - // We need to cast our definition of the uniform state to the undefined CPPPrelude::UniformState as - // that type is just a name to indicate what kind of thing needs to be passed in. + // We need to cast our definition of the uniform state to the undefined CPPPrelude::UniformState + // as that type is just a name to indicate what kind of thing needs to be passed in. func(&varyingInput, NULL, &uniformState); // bufferContents holds the output diff --git a/examples/example-base/example-base.cpp b/examples/example-base/example-base.cpp index 344611bed..9951d7cf2 100644 --- a/examples/example-base/example-base.cpp +++ b/examples/example-base/example-base.cpp @@ -1,4 +1,5 @@ #include "example-base.h" + #include #ifdef _WIN32 @@ -123,7 +124,11 @@ void WindowedAppBase::offlineRender() gTransientHeaps[0]->finish(); } -void WindowedAppBase::createFramebuffers(uint32_t width, uint32_t height, gfx::Format colorFormat, uint32_t frameBufferCount) +void WindowedAppBase::createFramebuffers( + uint32_t width, + uint32_t height, + gfx::Format colorFormat, + uint32_t frameBufferCount) { for (uint32_t i = 0; i < frameBufferCount; i++) { @@ -150,7 +155,8 @@ void WindowedAppBase::createFramebuffers(uint32_t width, uint32_t height, gfx::F colorBufferDesc.size.depth = 1; colorBufferDesc.format = colorFormat; colorBufferDesc.defaultState = ResourceState::RenderTarget; - colorBufferDesc.allowedStates = ResourceStateSet(ResourceState::RenderTarget, ResourceState::CopyDestination); + colorBufferDesc.allowedStates = + ResourceStateSet(ResourceState::RenderTarget, ResourceState::CopyDestination); colorBuffer = gDevice->createTextureResource(colorBufferDesc, nullptr); } else @@ -194,14 +200,21 @@ void WindowedAppBase::createOfflineFramebuffers() void WindowedAppBase::createSwapchainFramebuffers() { gFramebuffers.clear(); - createFramebuffers(gSwapchain->getDesc().width, gSwapchain->getDesc().height, - gSwapchain->getDesc().format, kSwapchainImageCount); + createFramebuffers( + gSwapchain->getDesc().width, + gSwapchain->getDesc().height, + gSwapchain->getDesc().format, + kSwapchainImageCount); } -ComPtr WindowedAppBase::createTextureFromFile(String fileName, int& textureWidth, int& textureHeight) +ComPtr WindowedAppBase::createTextureFromFile( + String fileName, + int& textureWidth, + int& textureHeight) { int channelsInFile = 0; - auto textureContent = stbi_load(fileName.getBuffer(), &textureWidth, &textureHeight, &channelsInFile, 4); + auto textureContent = + stbi_load(fileName.getBuffer(), &textureWidth, &textureHeight, &channelsInFile, 4); gfx::ITextureResource::Desc textureDesc = {}; textureDesc.allowedStates.add(ResourceState::ShaderResource); textureDesc.format = gfx::Format::R8G8B8A8_UNORM; @@ -222,9 +235,22 @@ ComPtr WindowedAppBase::createTextureFromFile(String fileNam subresData[0].strideZ = textureWidth * textureHeight * 4; // Build mipmaps. - struct RGBA { uint8_t v[4]; }; - auto castToRGBA = [](uint32_t v) { RGBA result; memcpy(&result, &v, 4); return result; }; - auto castToUint = [](RGBA v) { uint32_t result; memcpy(&result, &v, 4); return result; }; + struct RGBA + { + uint8_t v[4]; + }; + auto castToRGBA = [](uint32_t v) + { + RGBA result; + memcpy(&result, &v, 4); + return result; + }; + auto castToUint = [](RGBA v) + { + uint32_t result; + memcpy(&result, &v, 4); + return result; + }; int lastMipWidth = textureWidth; int lastMipHeight = textureHeight; @@ -248,7 +274,8 @@ ComPtr WindowedAppBase::createTextureFromFile(String fileNam RGBA pix; for (int c = 0; c < 4; c++) { - pix.v[c] = (uint8_t)(((uint32_t)pix1.v[c] + pix2.v[c] + pix3.v[c] + pix4.v[c]) / 4); + pix.v[c] = + (uint8_t)(((uint32_t)pix1.v[c] + pix2.v[c] + pix3.v[c] + pix4.v[c]) / 4); } mipMapData[m][y * w + x] = castToUint(pix); } @@ -286,40 +313,35 @@ void WindowedAppBase::windowSizeChanged() } } -int64_t getCurrentTime() { return std::chrono::high_resolution_clock::now().time_since_epoch().count(); } +int64_t getCurrentTime() +{ + return std::chrono::high_resolution_clock::now().time_since_epoch().count(); +} -int64_t getTimerFrequency() { return std::chrono::high_resolution_clock::period::den; } +int64_t getTimerFrequency() +{ + return std::chrono::high_resolution_clock::period::den; +} class DebugCallback : public IDebugCallback { public: virtual SLANG_NO_THROW void SLANG_MCALL - handleMessage(DebugMessageType type, DebugMessageSource source, const char* message) override + handleMessage(DebugMessageType type, DebugMessageSource source, const char* message) override { const char* typeStr = ""; switch (type) { - case DebugMessageType::Info: - typeStr = "INFO: "; - break; - case DebugMessageType::Warning: - typeStr = "WARNING: "; - break; - case DebugMessageType::Error: - typeStr = "ERROR: "; - break; - default: - break; + case DebugMessageType::Info: typeStr = "INFO: "; break; + case DebugMessageType::Warning: typeStr = "WARNING: "; break; + case DebugMessageType::Error: typeStr = "ERROR: "; break; + default: break; } const char* sourceStr = "[GraphicsLayer]: "; switch (source) { - case DebugMessageSource::Slang: - sourceStr = "[Slang]: "; - break; - case DebugMessageSource::Driver: - sourceStr = "[Driver]: "; - break; + case DebugMessageSource::Slang: sourceStr = "[Slang]: "; break; + case DebugMessageSource::Driver: sourceStr = "[Driver]: "; break; } printf("%s%s%s\n", sourceStr, typeStr, message); #ifdef _WIN32 @@ -338,5 +360,8 @@ void initDebugCallback() } #ifdef _WIN32 -void _Win32OutputDebugString(const char* str) { OutputDebugStringW(Slang::String(str).toWString().begin()); } +void _Win32OutputDebugString(const char* str) +{ + OutputDebugStringW(Slang::String(str).toWString().begin()); +} #endif diff --git a/examples/example-base/example-base.h b/examples/example-base/example-base.h index b97728e17..c10231c14 100644 --- a/examples/example-base/example-base.h +++ b/examples/example-base/example-base.h @@ -1,10 +1,10 @@ #pragma once #include "slang-gfx.h" -#include "tools/platform/window.h" #include "source/core/slang-basic.h" #include "source/core/slang-io.h" #include "test-base.h" +#include "tools/platform/window.h" #ifdef _WIN32 void _Win32OutputDebugString(const char* str); @@ -34,38 +34,52 @@ protected: int height, gfx::DeviceType deviceType = gfx::DeviceType::Default); - void createFramebuffers(uint32_t width, uint32_t height, gfx::Format colorFormat, uint32_t frameBufferCount); + void createFramebuffers( + uint32_t width, + uint32_t height, + gfx::Format colorFormat, + uint32_t frameBufferCount); void createSwapchainFramebuffers(); void createOfflineFramebuffers(); void mainLoop(); - Slang::ComPtr createTextureFromFile(Slang::String fileName, int& textureWidth, int& textureHeight); + Slang::ComPtr createTextureFromFile( + Slang::String fileName, + int& textureWidth, + int& textureHeight); virtual void windowSizeChanged(); protected: virtual void renderFrame(int framebufferIndex) = 0; + public: platform::Window* getWindow() { return gWindow.Ptr(); } virtual void finalize() { gQueue->waitOnHost(); } void offlineRender(); }; -struct ExampleResources { +struct ExampleResources +{ Slang::String baseDir; - ExampleResources(const Slang::String &dir) : baseDir(dir) {} - - Slang::String resolveResource(const char* fileName) const { - static const Slang::List directories { + ExampleResources(const Slang::String& dir) + : baseDir(dir) + { + } + + Slang::String resolveResource(const char* fileName) const + { + static const Slang::List directories{ "examples", "../examples", "../../examples", }; - - for (const Slang::String& dir : directories) { + + for (const Slang::String& dir : directories) + { Slang::StringBuilder pathSb; - pathSb << dir << "/" << baseDir << "/" << fileName; + pathSb << dir << "/" << baseDir << "/" << fileName; if (Slang::File::exists(pathSb.getBuffer())) return pathSb.toString(); } @@ -77,7 +91,8 @@ struct ExampleResources { int64_t getCurrentTime(); int64_t getTimerFrequency(); -template inline void reportError(const char* format, TArgs... args) +template +inline void reportError(const char* format, TArgs... args) { printf(format, args...); #ifdef _WIN32 @@ -87,7 +102,8 @@ template inline void reportError(const char* format, TArgs.. #endif } -template inline void log(const char* format, TArgs... args) +template +inline void log(const char* format, TArgs... args) { reportError(format, args...); } diff --git a/examples/example-base/test-base.cpp b/examples/example-base/test-base.cpp index 9d8ec8ce6..5d40f2d80 100644 --- a/examples/example-base/test-base.cpp +++ b/examples/example-base/test-base.cpp @@ -30,23 +30,30 @@ int TestBase::parseOption(int argc, char** argv) return 0; } -void TestBase::printEntrypointHashes(int entryPointCount, int targetCount, ComPtr& composedProgram) +void TestBase::printEntrypointHashes( + int entryPointCount, + int targetCount, + ComPtr& composedProgram) { for (int targetIndex = 0; targetIndex < targetCount; targetIndex++) { for (int entryPointIndex = 0; entryPointIndex < entryPointCount; entryPointIndex++) { ComPtr entryPointHashBlob; - composedProgram->getEntryPointHash(entryPointIndex, targetIndex, entryPointHashBlob.writeRef()); + composedProgram->getEntryPointHash( + entryPointIndex, + targetIndex, + entryPointHashBlob.writeRef()); Slang::StringBuilder strBuilder; - strBuilder << "callIdx: " << m_globalCounter << ", entrypoint: "<< entryPointIndex << ", target: " << targetIndex << ", hash: "; + strBuilder << "callIdx: " << m_globalCounter << ", entrypoint: " << entryPointIndex + << ", target: " << targetIndex << ", hash: "; m_globalCounter++; uint8_t* buffer = (uint8_t*)entryPointHashBlob->getBufferPointer(); for (size_t i = 0; i < entryPointHashBlob->getBufferSize(); i++) { - strBuilder<& composedProgram); + void printEntrypointHashes( + int entryPointCount, + int targetCount, + ComPtr& composedProgram); bool isTestMode() const { return m_isTestMode; } private: - bool m_isTestMode = false; - uint64_t m_globalCounter = 0; + bool m_isTestMode = false; + uint64_t m_globalCounter = 0; }; diff --git a/examples/gpu-printing/gpu-printing.cpp b/examples/gpu-printing/gpu-printing.cpp index aeca7aa9a..f71578554 100644 --- a/examples/gpu-printing/gpu-printing.cpp +++ b/examples/gpu-printing/gpu-printing.cpp @@ -2,7 +2,6 @@ #include "gpu-printing.h" #include - #include // This file implements the CPU side of a simple GPU printing @@ -39,7 +38,7 @@ void GPUPrinting::loadStrings(slang::ProgramLayout* slangReflection) // that appear in the linked program. // SlangUInt hashedStringCount = slangReflection->getHashedStringCount(); - for( SlangUInt ii = 0; ii < hashedStringCount; ++ii ) + for (SlangUInt ii = 0; ii < hashedStringCount; ++ii) { // For each string we can fetch its bytes from the Slang // reflection data. @@ -59,7 +58,8 @@ void GPUPrinting::loadStrings(slang::ProgramLayout* slangReflection) // The `GPUPrinting` implementation will store the mapping // from hash codes back to strings in a simple STL `map`. // - m_hashedStrings.insert(std::make_pair(hash, std::string(stringData, stringData + stringSize))); + m_hashedStrings.insert( + std::make_pair(hash, std::string(stringData, stringData + stringSize))); } } @@ -73,12 +73,12 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) // a granularity of 32-bits words, so we start by computing // how many words, total, will fit in the buffer. // - uint32_t dataWordCount = uint32_t(dataSize/ sizeof(uint32_t)); + uint32_t dataWordCount = uint32_t(dataSize / sizeof(uint32_t)); // // If the buffer doesn't even have enough space for the leading counter, // then there is nothing to print. // - if( dataWordCount < 1 ) + if (dataWordCount < 1) { fprintf(stderr, "error: expected at least 4 bytes in GPU printing buffer\n"); return; @@ -87,7 +87,7 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) // Otherwise, we set ourselves up to start reading data from the buffer // at a granularity of 32-bit words. // - const uint32_t* dataCursor = (const uint32_t*) data; + const uint32_t* dataCursor = (const uint32_t*)data; // The first word of a printing buffer gives us the total number of // words that were appended by GPU printing operations. @@ -106,20 +106,25 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) // larger buffer. // size_t totalBytesWritten = sizeof(uint32_t) * (wordsAppended + 1); - if( totalBytesWritten > dataSize ) + if (totalBytesWritten > dataSize) { - fprintf(stderr, "warning: GPU code attempted to write %llu bytes to the printing buffer, but only %llu bytes were available\n", (unsigned long long)totalBytesWritten, (unsigned long long)dataSize); + fprintf( + stderr, + "warning: GPU code attempted to write %llu bytes to the printing buffer, but only %llu " + "bytes were available\n", + (unsigned long long)totalBytesWritten, + (unsigned long long)dataSize); // If the buffer is full, then we only want to read through // to the end of what is available. // - dataEnd = ((const uint32_t*) data) + dataWordCount; + dataEnd = ((const uint32_t*)data) + dataWordCount; } // We will now proceed to read off "commands" from the buffer, // and execute those commands to print things to `stdout`. // - while( dataCursor < dataEnd ) + while (dataCursor < dataEnd) { // The first word of each command is encoded to hold both // an "opcode" for the command, and the number of "payload" @@ -135,7 +140,7 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) // avoid crashes from a command trying to fetch data past // the end of the buffer. // - if( payloadWordCount > size_t(dataCursor - dataEnd) ) + if (payloadWordCount > size_t(dataCursor - dataEnd)) { break; } @@ -149,7 +154,7 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) dataCursor += payloadWordCount; // What to do with a command depends a lot on which "op" was selected. - switch( op ) + switch (op) { default: // If we encounter an op that we don't understand, there is a change @@ -176,21 +181,21 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) // We will use a macro to avoid duplication the code shared // between these cases. // - #define CASE(OP, FORMAT, TYPE) \ - case GPUPrintingOp::OP: \ - { \ - TYPE value; \ - assert(payloadWordCount >= (sizeof(value) / sizeof(uint32_t))); \ - memcpy(&value, payloadWords, sizeof(value)); \ - printf(FORMAT, value); \ - } \ - break - - CASE(Int32, "%d", int); - CASE(UInt32, "%u", unsigned int); - CASE(Float32, "%f", float); - - #undef CASE +#define CASE(OP, FORMAT, TYPE) \ + case GPUPrintingOp::OP: \ + { \ + TYPE value; \ + assert(payloadWordCount >= (sizeof(value) / sizeof(uint32_t))); \ + memcpy(&value, payloadWords, sizeof(value)); \ + printf(FORMAT, value); \ + } \ + break + + CASE(Int32, "%d", int); + CASE(UInt32, "%u", unsigned int); + CASE(Float32, "%f", float); + +#undef CASE case GPUPrintingOp::String: { @@ -214,7 +219,7 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) // to appear in the GPU code. // auto iter = m_hashedStrings.find(hash); - if(iter == m_hashedStrings.end()) + if (iter == m_hashedStrings.end()) { // If we didn't have a string to match that hash code in // our map, we can continue trying to print, but it is @@ -230,7 +235,7 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) // // TODO: This code isn't robust against strings with // embeded null bytes. - //s + // s printf("%s", iter->second.c_str()); } break; @@ -248,7 +253,7 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) StringHash formatHash = *payloadWords++; auto iter = m_hashedStrings.find(formatHash); - if(iter == m_hashedStrings.end()) + if (iter == m_hashedStrings.end()) { // If we didn't have a string to match that hash code in // our map, we can continue trying to print, but it is @@ -270,14 +275,14 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) // const char* cursor = format.c_str(); const char* end = cursor + format.length(); - while( cursor != end ) + while (cursor != end) { int c = *cursor++; // If we see a byte other than `%`, then we can just // output it directly and keep scanning the format string. // - if( c != '%' ) + if (c != '%') { putchar(c); continue; @@ -289,7 +294,7 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) // If we are somehow at the end of the format // string, then the format was bad. // - if( cursor == end ) + if (cursor == end) { fprintf(stderr, "error: unexpected '%%' at and of format string\n"); break; @@ -299,7 +304,7 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) // the `%` character, then it is an escaped // `%` so we should just emit it as-is and move along. // - if( *cursor == '%' ) + if (*cursor == '%') { putchar(*cursor++); continue; @@ -317,52 +322,56 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) // read a single-byte specifier. // int specifier = *cursor++; - switch( specifier ) + switch (specifier) { default: - fprintf(stderr, "error: unexpected format specifier '%c' (0x%X)\n", specifier, specifier); + fprintf( + stderr, + "error: unexpected format specifier '%c' (0x%X)\n", + specifier, + specifier); break; - // When processing each format speecifier, we will - // read words from the payload, as necessary - // to yield a value of the expected type. - // - // To reduce the amount of boilerplate, we will - // use a macro to capture the shared code for - // common cases. - // - #define CASE(CHAR, FORMAT, TYPE) \ - case CHAR: \ - { \ - assert(payloadWords != payloadWordsEnd); \ - TYPE value; \ - memcpy(&value, payloadWords, sizeof(value)); \ - payloadWords += sizeof(value) / sizeof(uint32_t); \ - printf(FORMAT, value); \ - } \ - break + // When processing each format speecifier, we will + // read words from the payload, as necessary + // to yield a value of the expected type. + // + // To reduce the amount of boilerplate, we will + // use a macro to capture the shared code for + // common cases. + // +#define CASE(CHAR, FORMAT, TYPE) \ + case CHAR: \ + { \ + assert(payloadWords != payloadWordsEnd); \ + TYPE value; \ + memcpy(&value, payloadWords, sizeof(value)); \ + payloadWords += sizeof(value) / sizeof(uint32_t); \ + printf(FORMAT, value); \ + } \ + break case 'i': // `%i` is just an alias for `%d` - CASE('d', "%d", int); - CASE('u', "%u", unsigned int); - CASE('x', "%x", unsigned int); - CASE('X', "%X", unsigned int); - - // Note: all of our printing support for floating-point - // values will use the `float` type instead of `double`. - // This isn't compatible with C rules, but makes more sense - // for GPU code. - // - CASE('f', "%f", float); - CASE('F', "%F", float); - CASE('e', "%e", float); - CASE('E', "%E", float); - CASE('g', "%g", float); - CASE('G', "%G", float); - CASE('c', "%c", int); - - #undef CASE + CASE('d', "%d", int); + CASE('u', "%u", unsigned int); + CASE('x', "%x", unsigned int); + CASE('X', "%X", unsigned int); + + // Note: all of our printing support for floating-point + // values will use the `float` type instead of `double`. + // This isn't compatible with C rules, but makes more sense + // for GPU code. + // + CASE('f', "%f", float); + CASE('F', "%F", float); + CASE('e', "%e", float); + CASE('E', "%E", float); + CASE('g', "%g", float); + CASE('G', "%G", float); + CASE('c', "%c", int); + +#undef CASE case 's': { @@ -373,7 +382,7 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) assert(payloadWords != payloadWordsEnd); StringHash hash = *payloadWords++; auto iter = m_hashedStrings.find(hash); - if(iter == m_hashedStrings.end()) + if (iter == m_hashedStrings.end()) { fprintf(stderr, "error: string with unknown hash 0x%x\n", hash); continue; @@ -387,6 +396,4 @@ void GPUPrinting::processGPUPrintCommands(const void* data, size_t dataSize) break; } } - - } diff --git a/examples/gpu-printing/gpu-printing.h b/examples/gpu-printing/gpu-printing.h index 64eaf770a..84c036548 100644 --- a/examples/gpu-printing/gpu-printing.h +++ b/examples/gpu-printing/gpu-printing.h @@ -19,39 +19,39 @@ #include #include - /// Stores state used for executing print commands generated by GPU shaders +/// Stores state used for executing print commands generated by GPU shaders struct GPUPrinting { public: - /// Load any string literals used by a Slang program. - /// - /// The `slangReflection` should be the layout and reflection - /// object for a Slang shader program that might need to produce - /// printed output. This function will load any strings - /// referenced by the program into its database for mapping - /// string hashes back to the original strings. - /// + /// Load any string literals used by a Slang program. + /// + /// The `slangReflection` should be the layout and reflection + /// object for a Slang shader program that might need to produce + /// printed output. This function will load any strings + /// referenced by the program into its database for mapping + /// string hashes back to the original strings. + /// void loadStrings(slang::ProgramLayout* slangReflection); - /// Process a buffer of GPU printing commands and write output to `stdout`. - /// - /// This function attempts to read print commands from the buffer - /// pointed to by `data` and execute them to produce output. - /// - /// The buffer pointed at by `data` (of size `dataSize`) should be allocated - /// in host-visible memory. - /// - /// Before executing GPU work, the first four bytes pointed to by `data` - /// should have been cleared to zero. - /// - /// If GPU work has attempted to write more data than the buffer - /// can fit, a warning will be printed to `stderr`, and printing commands - /// that could not fit completely in the buffer will be skipped. - /// + /// Process a buffer of GPU printing commands and write output to `stdout`. + /// + /// This function attempts to read print commands from the buffer + /// pointed to by `data` and execute them to produce output. + /// + /// The buffer pointed at by `data` (of size `dataSize`) should be allocated + /// in host-visible memory. + /// + /// Before executing GPU work, the first four bytes pointed to by `data` + /// should have been cleared to zero. + /// + /// If GPU work has attempted to write more data than the buffer + /// can fit, a warning will be printed to `stderr`, and printing commands + /// that could not fit completely in the buffer will be skipped. + /// void processGPUPrintCommands(const void* data, size_t dataSize); private: typedef int StringHash; - std::map m_hashedStrings; + std::map m_hashedStrings; }; diff --git a/examples/gpu-printing/main.cpp b/examples/gpu-printing/main.cpp index fd15661dd..fa9f919dc 100644 --- a/examples/gpu-printing/main.cpp +++ b/examples/gpu-printing/main.cpp @@ -1,17 +1,16 @@ // main.cpp -#include - +#include "slang-com-ptr.h" #include "slang.h" -#include "slang-com-ptr.h" +#include using Slang::ComPtr; +#include "examples/example-base/example-base.h" +#include "gfx-util/shader-cursor.h" #include "gpu-printing.h" #include "slang-gfx.h" -#include "gfx-util/shader-cursor.h" -#include "tools/platform/window.h" #include "source/core/slang-basic.h" -#include "examples/example-base/example-base.h" +#include "tools/platform/window.h" using namespace gfx; @@ -23,7 +22,9 @@ ComPtr createSlangSession(gfx::IDevice* device) return slangSession; } -ComPtr compileShaderModuleFromFile(slang::ISession* slangSession, char const* filePath) +ComPtr compileShaderModuleFromFile( + slang::ISession* slangSession, + char const* filePath) { ComPtr slangModule; ComPtr diagnosticBlob; @@ -34,113 +35,121 @@ ComPtr compileShaderModuleFromFile(slang::ISession* slangSession return slangModule; } -struct ExampleProgram: public TestBase +struct ExampleProgram : public TestBase { -int gWindowWidth = 640; -int gWindowHeight = 480; + int gWindowWidth = 640; + int gWindowHeight = 480; -ComPtr gDevice; + ComPtr gDevice; -ComPtr gSlangSession; -ComPtr gSlangModule; -ComPtr gProgram; + ComPtr gSlangSession; + ComPtr gSlangModule; + ComPtr gProgram; -ComPtr gPipelineState; + ComPtr gPipelineState; -Slang::Dictionary gHashedStrings; + Slang::Dictionary gHashedStrings; -GPUPrinting gGPUPrinting; + GPUPrinting gGPUPrinting; -ComPtr loadComputeProgram(slang::IModule* slangModule, char const* entryPointName) -{ - ComPtr entryPoint; - slangModule->findEntryPointByName(entryPointName, entryPoint.writeRef()); - - ComPtr linkedProgram; - entryPoint->link(linkedProgram.writeRef()); - - if (isTestMode()) + ComPtr loadComputeProgram( + slang::IModule* slangModule, + char const* entryPointName) { - printEntrypointHashes(1, 1, linkedProgram); - } + ComPtr entryPoint; + slangModule->findEntryPointByName(entryPointName, entryPoint.writeRef()); - gGPUPrinting.loadStrings(linkedProgram->getLayout()); + ComPtr linkedProgram; + entryPoint->link(linkedProgram.writeRef()); - gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangGlobalScope = linkedProgram; + if (isTestMode()) + { + printEntrypointHashes(1, 1, linkedProgram); + } - auto shaderProgram = gDevice->createProgram(programDesc); + gGPUPrinting.loadStrings(linkedProgram->getLayout()); - return shaderProgram; -} + gfx::IShaderProgram::Desc programDesc = {}; + programDesc.slangGlobalScope = linkedProgram; -Result execute(int argc, char* argv[]) -{ - parseOption(argc, argv); - IDevice::Desc deviceDesc; - Result res = gfxCreateDevice(&deviceDesc, gDevice.writeRef()); - if(SLANG_FAILED(res)) return res; - - Slang::String path = resourceBase.resolveResource("kernels.slang"); - - gSlangSession = createSlangSession(gDevice); - gSlangModule = compileShaderModuleFromFile(gSlangSession, path.getBuffer()); - if(!gSlangModule) - return SLANG_FAIL; - - gProgram = loadComputeProgram(gSlangModule, "computeMain"); - if(!gProgram) - return SLANG_FAIL; - - ComputePipelineStateDesc desc; - desc.program = gProgram; - auto pipelineState = gDevice->createComputePipelineState(desc); - if(!pipelineState) return SLANG_FAIL; - - gPipelineState = pipelineState; - - size_t printBufferSize = 4 * 1024; // use a small-ish (4KB) buffer for print output - - IBufferResource::Desc printBufferDesc = {}; - printBufferDesc.type = IResource::Type::Buffer; - printBufferDesc.sizeInBytes = printBufferSize; - printBufferDesc.elementSize = sizeof(uint32_t); - printBufferDesc.defaultState = ResourceState::UnorderedAccess; - printBufferDesc.allowedStates = ResourceStateSet( - ResourceState::CopySource, ResourceState::CopyDestination, ResourceState::UnorderedAccess); - printBufferDesc.memoryType = MemoryType::DeviceLocal; - auto printBuffer = gDevice->createBufferResource(printBufferDesc); - - IResourceView::Desc printBufferViewDesc = {}; - printBufferViewDesc.type = IResourceView::Type::UnorderedAccess; - printBufferViewDesc.format = Format::Unknown; - auto printBufferView = gDevice->createBufferView(printBuffer, nullptr, printBufferViewDesc); - - ITransientResourceHeap::Desc transientResourceHeapDesc = {}; - transientResourceHeapDesc.constantBufferSize = 256; - auto transientHeap = gDevice->createTransientResourceHeap(transientResourceHeapDesc); - - ICommandQueue::Desc queueDesc = {ICommandQueue::QueueType::Graphics}; - auto queue = gDevice->createCommandQueue(queueDesc); - auto commandBuffer = transientHeap->createCommandBuffer(); - auto encoder = commandBuffer->encodeComputeCommands(); - auto rootShaderObject = encoder->bindPipeline(gPipelineState); - auto cursor = ShaderCursor(rootShaderObject); - cursor["gPrintBuffer"].setResource(printBufferView); - encoder->dispatchCompute(1, 1, 1); - encoder->bufferBarrier(printBuffer, ResourceState::UnorderedAccess, ResourceState::CopySource); - encoder->endEncoding(); - commandBuffer->close(); - queue->executeCommandBuffer(commandBuffer); - - ComPtr blob; - gDevice->readBufferResource(printBuffer, 0, printBufferSize, blob.writeRef()); - - gGPUPrinting.processGPUPrintCommands(blob->getBufferPointer(), printBufferSize); - - return SLANG_OK; -} + auto shaderProgram = gDevice->createProgram(programDesc); + + return shaderProgram; + } + Result execute(int argc, char* argv[]) + { + parseOption(argc, argv); + IDevice::Desc deviceDesc; + Result res = gfxCreateDevice(&deviceDesc, gDevice.writeRef()); + if (SLANG_FAILED(res)) + return res; + + Slang::String path = resourceBase.resolveResource("kernels.slang"); + + gSlangSession = createSlangSession(gDevice); + gSlangModule = compileShaderModuleFromFile(gSlangSession, path.getBuffer()); + if (!gSlangModule) + return SLANG_FAIL; + + gProgram = loadComputeProgram(gSlangModule, "computeMain"); + if (!gProgram) + return SLANG_FAIL; + + ComputePipelineStateDesc desc; + desc.program = gProgram; + auto pipelineState = gDevice->createComputePipelineState(desc); + if (!pipelineState) + return SLANG_FAIL; + + gPipelineState = pipelineState; + + size_t printBufferSize = 4 * 1024; // use a small-ish (4KB) buffer for print output + + IBufferResource::Desc printBufferDesc = {}; + printBufferDesc.type = IResource::Type::Buffer; + printBufferDesc.sizeInBytes = printBufferSize; + printBufferDesc.elementSize = sizeof(uint32_t); + printBufferDesc.defaultState = ResourceState::UnorderedAccess; + printBufferDesc.allowedStates = ResourceStateSet( + ResourceState::CopySource, + ResourceState::CopyDestination, + ResourceState::UnorderedAccess); + printBufferDesc.memoryType = MemoryType::DeviceLocal; + auto printBuffer = gDevice->createBufferResource(printBufferDesc); + + IResourceView::Desc printBufferViewDesc = {}; + printBufferViewDesc.type = IResourceView::Type::UnorderedAccess; + printBufferViewDesc.format = Format::Unknown; + auto printBufferView = gDevice->createBufferView(printBuffer, nullptr, printBufferViewDesc); + + ITransientResourceHeap::Desc transientResourceHeapDesc = {}; + transientResourceHeapDesc.constantBufferSize = 256; + auto transientHeap = gDevice->createTransientResourceHeap(transientResourceHeapDesc); + + ICommandQueue::Desc queueDesc = {ICommandQueue::QueueType::Graphics}; + auto queue = gDevice->createCommandQueue(queueDesc); + auto commandBuffer = transientHeap->createCommandBuffer(); + auto encoder = commandBuffer->encodeComputeCommands(); + auto rootShaderObject = encoder->bindPipeline(gPipelineState); + auto cursor = ShaderCursor(rootShaderObject); + cursor["gPrintBuffer"].setResource(printBufferView); + encoder->dispatchCompute(1, 1, 1); + encoder->bufferBarrier( + printBuffer, + ResourceState::UnorderedAccess, + ResourceState::CopySource); + encoder->endEncoding(); + commandBuffer->close(); + queue->executeCommandBuffer(commandBuffer); + + ComPtr blob; + gDevice->readBufferResource(printBuffer, 0, printBufferSize, blob.writeRef()); + + gGPUPrinting.processGPUPrintCommands(blob->getBufferPointer(), printBufferSize); + + return SLANG_OK; + } }; int main(int argc, char* argv[]) diff --git a/examples/hello-world/main.cpp b/examples/hello-world/main.cpp index 87d440901..e9585bde9 100644 --- a/examples/hello-world/main.cpp +++ b/examples/hello-world/main.cpp @@ -7,13 +7,12 @@ // The goal is to demonstrate how to use the Slang API to cross compile // shader code. // -#include "slang.h" -#include "slang-com-ptr.h" - -#include "vulkan-api.h" #include "examples/example-base/example-base.h" #include "examples/example-base/test-base.h" +#include "slang-com-ptr.h" +#include "slang.h" #include "source/core/slang-string-util.h" +#include "vulkan-api.h" using Slang::ComPtr; @@ -65,7 +64,6 @@ struct HelloWorldExample : public TestBase int run(); ~HelloWorldExample(); - }; int main(int argc, char* argv[]) @@ -102,8 +100,7 @@ int HelloWorldExample::initVulkanInstanceAndDevice() poolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; poolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; poolCreateInfo.queueFamilyIndex = vkAPI.queueFamilyIndex; - RETURN_ON_FAIL(vkAPI.vkCreateCommandPool( - vkAPI.device, &poolCreateInfo, nullptr, &commandPool)); + RETURN_ON_FAIL(vkAPI.vkCreateCommandPool(vkAPI.device, &poolCreateInfo, nullptr, &commandPool)); vkAPI.vkGetDeviceQueue(vkAPI.device, vkAPI.queueFamilyIndex, 0, &queue); return 0; @@ -204,7 +201,10 @@ int HelloWorldExample::createComputePipelineFromShader() { ComPtr diagnosticsBlob; SlangResult result = composedProgram->getEntryPointCode( - 0, 0, spirvCode.writeRef(), diagnosticsBlob.writeRef()); + 0, + 0, + spirvCode.writeRef(), + diagnosticsBlob.writeRef()); diagnoseIfNeeded(diagnosticsBlob); RETURN_ON_FAIL(result); @@ -238,13 +238,19 @@ int HelloWorldExample::createComputePipelineFromShader() } descSetLayoutCreateInfo.pBindings = bindings; RETURN_ON_FAIL(vkAPI.vkCreateDescriptorSetLayout( - vkAPI.device, &descSetLayoutCreateInfo, nullptr, &descriptorSetLayout)); + vkAPI.device, + &descSetLayoutCreateInfo, + nullptr, + &descriptorSetLayout)); VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}; pipelineLayoutCreateInfo.setLayoutCount = 1; pipelineLayoutCreateInfo.pSetLayouts = &descriptorSetLayout; RETURN_ON_FAIL(vkAPI.vkCreatePipelineLayout( - vkAPI.device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + vkAPI.device, + &pipelineLayoutCreateInfo, + nullptr, + &pipelineLayout)); // Next we create a shader module from the compiled SPIRV code. VkShaderModuleCreateInfo shaderCreateInfo = {VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO}; @@ -263,7 +269,12 @@ int HelloWorldExample::createComputePipelineFromShader() pipelineCreateInfo.stage.pName = "main"; pipelineCreateInfo.layout = pipelineLayout; RETURN_ON_FAIL(vkAPI.vkCreateComputePipelines( - vkAPI.device, VK_NULL_HANDLE, 1, &pipelineCreateInfo, nullptr, &pipeline)); + vkAPI.device, + VK_NULL_HANDLE, + 1, + &pipelineCreateInfo, + nullptr, + &pipeline)); // We can destroy shader module now since it will no longer be used. vkAPI.vkDestroyShaderModule(vkAPI.device, vkShaderModule, nullptr); @@ -287,7 +298,8 @@ int HelloWorldExample::createInOutBuffers() vkAPI.vkGetBufferMemoryRequirements(vkAPI.device, inOutBuffers[i], &memoryReqs); int memoryTypeIndex = vkAPI.findMemoryTypeIndex( - memoryReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + memoryReqs.memoryTypeBits, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); assert(memoryTypeIndex >= 0); VkMemoryPropertyFlags actualMemoryProperites = @@ -347,7 +359,10 @@ int HelloWorldExample::createInOutBuffers() commandBufferAllocInfo.commandBufferCount = 1; commandBufferAllocInfo.commandPool = commandPool; commandBufferAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - RETURN_ON_FAIL(vkAPI.vkAllocateCommandBuffers(vkAPI.device, &commandBufferAllocInfo, &uploadCommandBuffer)); + RETURN_ON_FAIL(vkAPI.vkAllocateCommandBuffers( + vkAPI.device, + &commandBufferAllocInfo, + &uploadCommandBuffer)); VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO}; vkAPI.vkBeginCommandBuffer(uploadCommandBuffer, &beginInfo); @@ -378,7 +393,10 @@ int HelloWorldExample::dispatchCompute() descriptorPoolCreateInfo.flags = 0; VkDescriptorPool descriptorPool = VK_NULL_HANDLE; RETURN_ON_FAIL(vkAPI.vkCreateDescriptorPool( - vkAPI.device, &descriptorPoolCreateInfo, nullptr, &descriptorPool)); + vkAPI.device, + &descriptorPoolCreateInfo, + nullptr, + &descriptorPool)); // Allocate descriptor set. VkDescriptorSetAllocateInfo descSetAllocInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO}; diff --git a/examples/hello-world/vulkan-api.cpp b/examples/hello-world/vulkan-api.cpp index 3581563d4..95c4a512e 100644 --- a/examples/hello-world/vulkan-api.cpp +++ b/examples/hello-world/vulkan-api.cpp @@ -1,16 +1,17 @@ #include "vulkan-api.h" + #include "slang.h" -#include -#include #include +#include +#include #include #include #if SLANG_WINDOWS_FAMILY -# include +#include #else -# include +#include #endif #if _DEBUG @@ -25,7 +26,8 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback( int32_t /*msgCode*/, const char* pLayerPrefix, const char* pMsg, - void* /*pUserData*/) + void* /*pUserData*/ +) { printf("[%s]: %s\n", pLayerPrefix, pMsg); return 1; @@ -62,7 +64,7 @@ int initializeVulkanDevice(VulkanAPI& api) uint32_t propertyCount; if (api.vkEnumerateInstanceLayerProperties(&propertyCount, nullptr) != 0) return -1; - std::vector< VkLayerProperties> properties(propertyCount); + std::vector properties(propertyCount); if (api.vkEnumerateInstanceLayerProperties(&propertyCount, properties.data()) != 0) return -1; for (const auto& p : properties) @@ -119,17 +121,19 @@ int initializeVulkanDevice(VulkanAPI& api) debugCreateInfo.flags = debugFlags; RETURN_ON_FAIL(api.vkCreateDebugReportCallbackEXT( - api.instance, &debugCreateInfo, nullptr, &api.debugReportCallback)); + api.instance, + &debugCreateInfo, + nullptr, + &api.debugReportCallback)); } // Enumerate physical devices. uint32_t numPhysicalDevices = 0; - RETURN_ON_FAIL( - api.vkEnumeratePhysicalDevices(api.instance, &numPhysicalDevices, nullptr)); + RETURN_ON_FAIL(api.vkEnumeratePhysicalDevices(api.instance, &numPhysicalDevices, nullptr)); std::vector physicalDevices; physicalDevices.resize(numPhysicalDevices); - RETURN_ON_FAIL(api.vkEnumeratePhysicalDevices( - api.instance, &numPhysicalDevices, &physicalDevices[0])); + RETURN_ON_FAIL( + api.vkEnumeratePhysicalDevices(api.instance, &numPhysicalDevices, &physicalDevices[0])); // We will use device 0. api.initPhysicalDevice(physicalDevices[0]); @@ -145,7 +149,9 @@ int initializeVulkanDevice(VulkanAPI& api) std::vector queueFamilies; queueFamilies.resize(numQueueFamilies); api.vkGetPhysicalDeviceQueueFamilyProperties( - api.physicalDevice, &numQueueFamilies, &queueFamilies[0]); + api.physicalDevice, + &numQueueFamilies, + &queueFamilies[0]); // Find a queue that can service our needs. auto requiredQueueFlags = VK_QUEUE_COMPUTE_BIT; diff --git a/examples/hello-world/vulkan-api.h b/examples/hello-world/vulkan-api.h index 89ca9747d..ab0822569 100644 --- a/examples/hello-world/vulkan-api.h +++ b/examples/hello-world/vulkan-api.h @@ -121,12 +121,12 @@ struct VulkanAPI }; #define RETURN_ON_FAIL(x) \ - { \ - auto _res = x; \ - if (_res != 0) \ - { \ - return -1; \ - } \ + { \ + auto _res = x; \ + if (_res != 0) \ + { \ + return -1; \ + } \ } // Loads Vulkan library and creates a VkDevice. diff --git a/examples/model-viewer/main.cpp b/examples/model-viewer/main.cpp index 7ca5eeb74..7faaf5569 100644 --- a/examples/model-viewer/main.cpp +++ b/examples/model-viewer/main.cpp @@ -16,21 +16,21 @@ // We still need to include the Slang header to use the Slang API // -#include "slang.h" #include "slang-com-helper.h" +#include "slang.h" // We will again make use of a graphics API abstraction // layer that implements the shader-object idiom based on Slang's // `ParameterBlock` and `interface` features to simplify shader specialization // and parameter binding. // +#include "examples/example-base/example-base.h" #include "slang-gfx.h" #include "tools/gfx-util/shader-cursor.h" +#include "tools/platform/gui.h" #include "tools/platform/model.h" #include "tools/platform/vector-math.h" #include "tools/platform/window.h" -#include "tools/platform/gui.h" -#include "examples/example-base/example-base.h" #include #include @@ -51,7 +51,7 @@ struct RendererContext slang::TypeReflection* perViewShaderType; slang::TypeReflection* perModelShaderType; - TestBase *pTestBase; + TestBase* pTestBase; Result init(IDevice* inDevice, TestBase* inTestBase) { @@ -60,9 +60,8 @@ struct RendererContext pTestBase = inTestBase; Slang::String path = resourceBase.resolveResource("shaders.slang").getBuffer(); - shaderModule = device->getSlangSession()->loadModule( - path.getBuffer(), - diagnostic.writeRef()); + shaderModule = + device->getSlangSession()->loadModule(path.getBuffer(), diagnostic.writeRef()); diagnoseIfNeeded(diagnostic); if (!shaderModule) return SLANG_FAIL; @@ -165,9 +164,9 @@ struct Material : RefObject // struct SimpleMaterial : Material { - glm::vec3 diffuseColor; - glm::vec3 specularColor; - float specularity = 1.0f; + glm::vec3 diffuseColor; + glm::vec3 specularColor; + float specularity = 1.0f; // Create a shader object that contains the type info and parameter values // that represent an instance of `SimpleMaterial`. @@ -194,20 +193,20 @@ struct SimpleMaterial : Material // struct Mesh : RefObject { - RefPtr material; - int firstIndex; - int indexCount; + RefPtr material; + int firstIndex; + int indexCount; }; struct Model : RefObject { typedef platform::ModelLoader::Vertex Vertex; - ComPtr vertexBuffer; - ComPtr indexBuffer; - PrimitiveTopology primitiveTopology; - int vertexCount; - int indexCount; - std::vector> meshes; + ComPtr vertexBuffer; + ComPtr indexBuffer; + PrimitiveTopology primitiveTopology; + int vertexCount; + int indexCount; + std::vector> meshes; }; // // Loading a model from disk is done with the help of some utility @@ -216,10 +215,10 @@ struct Model : RefObject // used for its representation. // RefPtr loadModel( - RendererContext* context, - char const* inputPath, + RendererContext* context, + char const* inputPath, platform::ModelLoader::LoadFlags loadFlags = 0, - float scale = 1.0f) + float scale = 1.0f) { // The model loading interface using a C++ interface of // callback functions to handle creating the application-specific @@ -308,7 +307,7 @@ struct Light : RefObject // The shader object for a light will be stashed here // after it is created. -// ComPtr shaderObject; + // ComPtr shaderObject; }; // Helper function to retrieve the underlying shader type of `T`. @@ -411,8 +410,7 @@ struct LightEnvLayout : public RefObject { auto program = context->slangReflection; std::stringstream typeNameBuilder; - typeNameBuilder << "LightArray<" << lightType->getName() << "," << maximumCount - << ">"; + typeNameBuilder << "LightArray<" << lightType->getName() << "," << maximumCount << ">"; layout.typeName = typeNameBuilder.str(); } @@ -420,7 +418,8 @@ struct LightEnvLayout : public RefObject mapLightTypeToArrayIndex.insert(std::make_pair(lightType, arrayIndex)); } - template void addLightType(RendererContext* context, Int maximumCount) + template + void addLightType(RendererContext* context, Int maximumCount) { addLightType(context, getShaderType(context), maximumCount); } @@ -459,8 +458,7 @@ struct LightEnv : public RefObject RefPtr layout; RendererContext* context; LightEnv(RefPtr layout, RendererContext* inContext) - : layout(layout) - , context(inContext) + : layout(layout), context(inContext) { for (auto arrayLayout : layout->lightArrayLayouts) { @@ -640,329 +638,324 @@ struct LightEnv : public RefObject // struct ModelViewer : WindowedAppBase { -RendererContext context; + RendererContext context; -// Most of the application state is stored in the list of loaded models, -// as well as the active light source (a single light for now). -// -std::vector> gModels; -RefPtr lightEnv; + // Most of the application state is stored in the list of loaded models, + // as well as the active light source (a single light for now). + // + std::vector> gModels; + RefPtr lightEnv; -// The pipeline state object we will use to draw models. -ComPtr gPipelineState; + // The pipeline state object we will use to draw models. + ComPtr gPipelineState; -// During startup the application will load one or more models and -// add them to the `gModels` list. -// -void loadAndAddModel( - char const* inputPath, - platform::ModelLoader::LoadFlags loadFlags = 0, - float scale = 1.0f) -{ - auto model = loadModel(&context, inputPath, loadFlags, scale); - if(!model) return; - gModels.push_back(model); -} + // During startup the application will load one or more models and + // add them to the `gModels` list. + // + void loadAndAddModel( + char const* inputPath, + platform::ModelLoader::LoadFlags loadFlags = 0, + float scale = 1.0f) + { + auto model = loadModel(&context, inputPath, loadFlags, scale); + if (!model) + return; + gModels.push_back(model); + } -// Our "simulation" state consists of just a few values. -// -uint64_t lastTime = 0; + // Our "simulation" state consists of just a few values. + // + uint64_t lastTime = 0; -//glm::vec3 lightDir = normalize(glm::vec3(10, 10, 10)); -//glm::vec3 lightColor = glm::vec3(1, 1, 1); + // glm::vec3 lightDir = normalize(glm::vec3(10, 10, 10)); + // glm::vec3 lightColor = glm::vec3(1, 1, 1); -glm::vec3 cameraPosition = glm::vec3(1.75, 1.25, 5); -glm::quat cameraOrientation = glm::quat(1, glm::vec3(0)); + glm::vec3 cameraPosition = glm::vec3(1.75, 1.25, 5); + glm::quat cameraOrientation = glm::quat(1, glm::vec3(0)); -float translationScale = 0.5f; -float rotationScale = 0.025f; + float translationScale = 0.5f; + float rotationScale = 0.025f; -// In order to control camera movement, we will -// use good old WASD -bool wPressed = false; -bool aPressed = false; -bool sPressed = false; -bool dPressed = false; + // In order to control camera movement, we will + // use good old WASD + bool wPressed = false; + bool aPressed = false; + bool sPressed = false; + bool dPressed = false; -bool isMouseDown = false; -float lastMouseX = 0.0f; -float lastMouseY = 0.0f; + bool isMouseDown = false; + float lastMouseX = 0.0f; + float lastMouseY = 0.0f; -void setKeyState(platform::KeyCode key, bool state) -{ - switch (key) + void setKeyState(platform::KeyCode key, bool state) { - default: - break; - case platform::KeyCode::W: - wPressed = state; - break; - case platform::KeyCode::A: - aPressed = state; - break; - case platform::KeyCode::S: - sPressed = state; - break; - case platform::KeyCode::D: - dPressed = state; - break; + switch (key) + { + default: break; + case platform::KeyCode::W: wPressed = state; break; + case platform::KeyCode::A: aPressed = state; break; + case platform::KeyCode::S: sPressed = state; break; + case platform::KeyCode::D: dPressed = state; break; + } } -} -void onKeyDown(platform::KeyEventArgs args) { setKeyState(args.key, true); } -void onKeyUp(platform::KeyEventArgs args) { setKeyState(args.key, false); } + void onKeyDown(platform::KeyEventArgs args) { setKeyState(args.key, true); } + void onKeyUp(platform::KeyEventArgs args) { setKeyState(args.key, false); } -void onMouseDown(platform::MouseEventArgs args) -{ - isMouseDown = true; - lastMouseX = (float)args.x; - lastMouseY = (float)args.y; -} - -void onMouseMove(platform::MouseEventArgs args) -{ - if (isMouseDown) + void onMouseDown(platform::MouseEventArgs args) { - float deltaX = args.x - lastMouseX; - float deltaY = args.y - lastMouseY; - - cameraOrientation = - glm::rotate(cameraOrientation, -deltaX * rotationScale, glm::vec3(0, 1, 0)); - cameraOrientation = - glm::rotate(cameraOrientation, -deltaY * rotationScale, glm::vec3(1, 0, 0)); - - cameraOrientation = normalize(cameraOrientation); - + isMouseDown = true; lastMouseX = (float)args.x; lastMouseY = (float)args.y; } -} -void onMouseUp(platform::MouseEventArgs args) -{ - isMouseDown = false; -} -// The overall initialization logic is quite similar to -// the earlier example. The biggest difference is that we -// create instances of our application-specific parameter -// block layout and effect types instead of just creating -// raw graphics API objects. -// -Result initialize() -{ - initializeBase("Model Viewer", 1024, 768); - if (!isTestMode()) + void onMouseMove(platform::MouseEventArgs args) { - gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { onMouseMove(e); }; - gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { onMouseUp(e); }; - gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { onMouseDown(e); }; - gWindow->events.keyDown = [this](const platform::KeyEventArgs& e) { onKeyDown(e); }; - gWindow->events.keyUp = [this](const platform::KeyEventArgs& e) { onKeyUp(e); }; - } + if (isMouseDown) + { + float deltaX = args.x - lastMouseX; + float deltaY = args.y - lastMouseY; - // Initialize `RendererContext`, which loads the shader module from file. - SLANG_RETURN_ON_FAIL(context.init(gDevice, this)); + cameraOrientation = + glm::rotate(cameraOrientation, -deltaX * rotationScale, glm::vec3(0, 1, 0)); + cameraOrientation = + glm::rotate(cameraOrientation, -deltaY * rotationScale, glm::vec3(1, 0, 0)); + cameraOrientation = normalize(cameraOrientation); - InputElementDesc inputElements[] = { - {"POSITION", 0, Format::R32G32B32_FLOAT, offsetof(Model::Vertex, position) }, - {"NORMAL", 0, Format::R32G32B32_FLOAT, offsetof(Model::Vertex, normal) }, - {"UV", 0, Format::R32G32_FLOAT, offsetof(Model::Vertex, uv) }, - }; - auto inputLayout = gDevice->createInputLayout( - sizeof(Model::Vertex), - &inputElements[0], - 3); - if(!inputLayout) return SLANG_FAIL; - - // Create the pipeline state object for drawing models. - GraphicsPipelineStateDesc pipelineStateDesc = {}; - pipelineStateDesc.program = context.shaderProgram; - pipelineStateDesc.framebufferLayout = gFramebufferLayout; - pipelineStateDesc.inputLayout = inputLayout; - pipelineStateDesc.primitiveType = PrimitiveType::Triangle; - pipelineStateDesc.depthStencil.depthFunc = ComparisonFunc::LessEqual; - pipelineStateDesc.depthStencil.depthTestEnable = true; - gPipelineState = gDevice->createGraphicsPipelineState(pipelineStateDesc); - - // We will create a lighting environment layout that can hold a few point - // and directional lights, and then initialize a lighting environment - // with just a single point light. + lastMouseX = (float)args.x; + lastMouseY = (float)args.y; + } + } + void onMouseUp(platform::MouseEventArgs args) { isMouseDown = false; } + + // The overall initialization logic is quite similar to + // the earlier example. The biggest difference is that we + // create instances of our application-specific parameter + // block layout and effect types instead of just creating + // raw graphics API objects. // - RefPtr lightEnvLayout = new LightEnvLayout(); - lightEnvLayout->addLightType(&context, 10); - lightEnvLayout->addLightType(&context, 2); + Result initialize() + { + initializeBase("Model Viewer", 1024, 768); + if (!isTestMode()) + { + gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) + { onMouseMove(e); }; + gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { onMouseUp(e); }; + gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) + { onMouseDown(e); }; + gWindow->events.keyDown = [this](const platform::KeyEventArgs& e) { onKeyDown(e); }; + gWindow->events.keyUp = [this](const platform::KeyEventArgs& e) { onKeyUp(e); }; + } - lightEnv = new LightEnv(lightEnvLayout, &context); + // Initialize `RendererContext`, which loads the shader module from file. + SLANG_RETURN_ON_FAIL(context.init(gDevice, this)); - RefPtr pointLight = new PointLight(); - pointLight->position = glm::vec3(5, 3, 1); - pointLight->intensity = glm::vec3(10); - lightEnv->add(pointLight); - // Once we have created all our graphcis API and application resources, - // we can start to load models. For now we are keeping things extremely - // simple by using a trivial `.obj` file that can be checked into source - // control. - // - // Support for loading more interesting/complex models will be added - // to this example over time (although model loading is *not* the focus). - // - Slang::String path = resourceBase.resolveResource("cube.obj").getBuffer(); - loadAndAddModel(path.getBuffer()); + InputElementDesc inputElements[] = { + {"POSITION", 0, Format::R32G32B32_FLOAT, offsetof(Model::Vertex, position)}, + {"NORMAL", 0, Format::R32G32B32_FLOAT, offsetof(Model::Vertex, normal)}, + {"UV", 0, Format::R32G32_FLOAT, offsetof(Model::Vertex, uv)}, + }; + auto inputLayout = gDevice->createInputLayout(sizeof(Model::Vertex), &inputElements[0], 3); + if (!inputLayout) + return SLANG_FAIL; - return SLANG_OK; -} + // Create the pipeline state object for drawing models. + GraphicsPipelineStateDesc pipelineStateDesc = {}; + pipelineStateDesc.program = context.shaderProgram; + pipelineStateDesc.framebufferLayout = gFramebufferLayout; + pipelineStateDesc.inputLayout = inputLayout; + pipelineStateDesc.primitiveType = PrimitiveType::Triangle; + pipelineStateDesc.depthStencil.depthFunc = ComparisonFunc::LessEqual; + pipelineStateDesc.depthStencil.depthTestEnable = true; + gPipelineState = gDevice->createGraphicsPipelineState(pipelineStateDesc); + + // We will create a lighting environment layout that can hold a few point + // and directional lights, and then initialize a lighting environment + // with just a single point light. + // + RefPtr lightEnvLayout = new LightEnvLayout(); + lightEnvLayout->addLightType(&context, 10); + lightEnvLayout->addLightType(&context, 2); -// With the setup work done, we can look at the per-frame rendering -// logic to see how the application will drive the `RenderContext` -// type to perform both shader parameter binding and code specialization. -// -void renderFrame(int frameIndex) override -{ - // In order to see that things are rendering properly we need some - // kind of animation, so we will compute a crude delta-time value here. - // - if(!lastTime) lastTime = getCurrentTime(); - uint64_t currentTime = getCurrentTime(); - float deltaTime = float(double(currentTime - lastTime) / double(getTimerFrequency())); - lastTime = currentTime; + lightEnv = new LightEnv(lightEnvLayout, &context); - // We will use the GLM library to do the matrix math required - // to set up our various transformation matrices. - // - glm::mat4x4 identity = glm::mat4x4(1.0f); + RefPtr pointLight = new PointLight(); + pointLight->position = glm::vec3(5, 3, 1); + pointLight->intensity = glm::vec3(10); + lightEnv->add(pointLight); - platform::Rect clientRect{}; - if (isTestMode()) - { - clientRect.width = 1024; - clientRect.height = 768; - } - else - { - clientRect = getWindow()->getClientRect(); - } - if (clientRect.height == 0) - return; - glm::mat4x4 projection = glm::perspectiveRH_ZO( - glm::radians(60.0f), float(clientRect.width) / float(clientRect.height), - 0.1f, - 1000.0f); - - // We are implementing a *very* basic 6DOF first-person - // camera movement model. - // - glm::mat3x3 cameraOrientationMat(cameraOrientation); - glm::vec3 forward = -cameraOrientationMat[2]; - glm::vec3 right = cameraOrientationMat[0]; - - glm::vec3 movement = glm::vec3(0); - if(wPressed) movement += forward; - if(sPressed) movement -= forward; - if(aPressed) movement -= right; - if(dPressed) movement += right; - - cameraPosition += deltaTime * translationScale * movement; - - glm::mat4x4 view = identity; - view *= glm::mat4x4(inverse(cameraOrientation)); - view = glm::translate(view, -cameraPosition); - - glm::mat4x4 viewProjection = projection * view; - auto deviceInfo = gDevice->getDeviceInfo(); - glm::mat4x4 correctionMatrix; - memcpy(&correctionMatrix, deviceInfo.identityProjectionMatrix, sizeof(float)*16); - viewProjection = correctionMatrix * viewProjection; - // glm uses column-major layout, we need to translate it to row-major. - viewProjection = glm::transpose(viewProjection); - - auto drawCommandBuffer = gTransientHeaps[frameIndex]->createCommandBuffer(); - auto drawCommandEncoder = - drawCommandBuffer->encodeRenderCommands(gRenderPass, gFramebuffers[frameIndex]); - gfx::Viewport viewport = {}; - viewport.maxZ = 1.0f; - viewport.extentX = (float)clientRect.width; - viewport.extentY = (float)clientRect.height; - drawCommandEncoder->setViewportAndScissor(viewport); - drawCommandEncoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); - - // We are only rendering one view, so we can fill in a per-view - // shader object once and use it across all draw calls. - // + // Once we have created all our graphcis API and application resources, + // we can start to load models. For now we are keeping things extremely + // simple by using a trivial `.obj` file that can be checked into source + // control. + // + // Support for loading more interesting/complex models will be added + // to this example over time (although model loading is *not* the focus). + // + Slang::String path = resourceBase.resolveResource("cube.obj").getBuffer(); + loadAndAddModel(path.getBuffer()); - auto viewShaderObject = gDevice->createShaderObject(context.perViewShaderType); - { - ShaderCursor cursor(viewShaderObject); - cursor["viewProjection"].setData(&viewProjection, sizeof(viewProjection)); - cursor["eyePosition"].setData(&cameraPosition, sizeof(cameraPosition)); + return SLANG_OK; } - // The majority of our rendering logic is handled as a loop - // over the models in the scene, and their meshes. + + // With the setup work done, we can look at the per-frame rendering + // logic to see how the application will drive the `RenderContext` + // type to perform both shader parameter binding and code specialization. // - for(auto& model : gModels) + void renderFrame(int frameIndex) override { - drawCommandEncoder->setVertexBuffer(0, model->vertexBuffer); - drawCommandEncoder->setIndexBuffer(model->indexBuffer, Format::R32_UINT); - // For each model we provide a parameter - // block that holds the per-model transformation - // parameters, corresponding to the `PerModel` type - // in the shader code. - glm::mat4x4 modelTransform = identity; - glm::mat4x4 inverseTransposeModelTransform = inverse(transpose(modelTransform)); - auto modelShaderObject = gDevice->createShaderObject(context.perModelShaderType); + // In order to see that things are rendering properly we need some + // kind of animation, so we will compute a crude delta-time value here. + // + if (!lastTime) + lastTime = getCurrentTime(); + uint64_t currentTime = getCurrentTime(); + float deltaTime = float(double(currentTime - lastTime) / double(getTimerFrequency())); + lastTime = currentTime; + + // We will use the GLM library to do the matrix math required + // to set up our various transformation matrices. + // + glm::mat4x4 identity = glm::mat4x4(1.0f); + + platform::Rect clientRect{}; + if (isTestMode()) { - ShaderCursor cursor(modelShaderObject); - cursor["modelTransform"].setData(&modelTransform, sizeof(modelTransform)); - cursor["inverseTransposeModelTransform"].setData( - &inverseTransposeModelTransform, sizeof(inverseTransposeModelTransform)); + clientRect.width = 1024; + clientRect.height = 768; } - - auto lightShaderObject = lightEnv->createShaderObject(); - - // Now we loop over the meshes in the model. + else + { + clientRect = getWindow()->getClientRect(); + } + if (clientRect.height == 0) + return; + glm::mat4x4 projection = glm::perspectiveRH_ZO( + glm::radians(60.0f), + float(clientRect.width) / float(clientRect.height), + 0.1f, + 1000.0f); + + // We are implementing a *very* basic 6DOF first-person + // camera movement model. // - // A more advanced rendering loop would sort things by material - // rather than by model, to avoid overly frequent state changes. - // We are just doing something simple for the purposes of an - // exmple program. + glm::mat3x3 cameraOrientationMat(cameraOrientation); + glm::vec3 forward = -cameraOrientationMat[2]; + glm::vec3 right = cameraOrientationMat[0]; + + glm::vec3 movement = glm::vec3(0); + if (wPressed) + movement += forward; + if (sPressed) + movement -= forward; + if (aPressed) + movement -= right; + if (dPressed) + movement += right; + + cameraPosition += deltaTime * translationScale * movement; + + glm::mat4x4 view = identity; + view *= glm::mat4x4(inverse(cameraOrientation)); + view = glm::translate(view, -cameraPosition); + + glm::mat4x4 viewProjection = projection * view; + auto deviceInfo = gDevice->getDeviceInfo(); + glm::mat4x4 correctionMatrix; + memcpy(&correctionMatrix, deviceInfo.identityProjectionMatrix, sizeof(float) * 16); + viewProjection = correctionMatrix * viewProjection; + // glm uses column-major layout, we need to translate it to row-major. + viewProjection = glm::transpose(viewProjection); + + auto drawCommandBuffer = gTransientHeaps[frameIndex]->createCommandBuffer(); + auto drawCommandEncoder = + drawCommandBuffer->encodeRenderCommands(gRenderPass, gFramebuffers[frameIndex]); + gfx::Viewport viewport = {}; + viewport.maxZ = 1.0f; + viewport.extentX = (float)clientRect.width; + viewport.extentY = (float)clientRect.height; + drawCommandEncoder->setViewportAndScissor(viewport); + drawCommandEncoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); + + // We are only rendering one view, so we can fill in a per-view + // shader object once and use it across all draw calls. // - for(auto& mesh : model->meshes) + + auto viewShaderObject = gDevice->createShaderObject(context.perViewShaderType); { - // Set the pipeline and binding state for drawing each mesh. - auto rootObject = drawCommandEncoder->bindPipeline(gPipelineState); - ShaderCursor rootCursor(rootObject); - rootCursor["gViewParams"].setObject(viewShaderObject); - rootCursor["gModelParams"].setObject(modelShaderObject); - rootCursor["gLightEnv"].setObject(lightShaderObject); - - // Each mesh has a material, and each material has its own - // parameter block that was created at load time, so we - // can just re-use the persistent parameter block for the - // chosen material. + ShaderCursor cursor(viewShaderObject); + cursor["viewProjection"].setData(&viewProjection, sizeof(viewProjection)); + cursor["eyePosition"].setData(&cameraPosition, sizeof(cameraPosition)); + } + // The majority of our rendering logic is handled as a loop + // over the models in the scene, and their meshes. + // + for (auto& model : gModels) + { + drawCommandEncoder->setVertexBuffer(0, model->vertexBuffer); + drawCommandEncoder->setIndexBuffer(model->indexBuffer, Format::R32_UINT); + // For each model we provide a parameter + // block that holds the per-model transformation + // parameters, corresponding to the `PerModel` type + // in the shader code. + glm::mat4x4 modelTransform = identity; + glm::mat4x4 inverseTransposeModelTransform = inverse(transpose(modelTransform)); + auto modelShaderObject = gDevice->createShaderObject(context.perModelShaderType); + { + ShaderCursor cursor(modelShaderObject); + cursor["modelTransform"].setData(&modelTransform, sizeof(modelTransform)); + cursor["inverseTransposeModelTransform"].setData( + &inverseTransposeModelTransform, + sizeof(inverseTransposeModelTransform)); + } + + auto lightShaderObject = lightEnv->createShaderObject(); + + // Now we loop over the meshes in the model. // - // Note that binding the material parameter block here is - // both selecting the values to use for various material - // parameters as well as the *code* to use for material - // evaluation (based on the concrete shader type that - // is implementing the `IMaterial` interface). + // A more advanced rendering loop would sort things by material + // rather than by model, to avoid overly frequent state changes. + // We are just doing something simple for the purposes of an + // exmple program. // - rootCursor["gMaterial"].setObject(mesh->material->shaderObject); + for (auto& mesh : model->meshes) + { + // Set the pipeline and binding state for drawing each mesh. + auto rootObject = drawCommandEncoder->bindPipeline(gPipelineState); + ShaderCursor rootCursor(rootObject); + rootCursor["gViewParams"].setObject(viewShaderObject); + rootCursor["gModelParams"].setObject(modelShaderObject); + rootCursor["gLightEnv"].setObject(lightShaderObject); + + // Each mesh has a material, and each material has its own + // parameter block that was created at load time, so we + // can just re-use the persistent parameter block for the + // chosen material. + // + // Note that binding the material parameter block here is + // both selecting the values to use for various material + // parameters as well as the *code* to use for material + // evaluation (based on the concrete shader type that + // is implementing the `IMaterial` interface). + // + rootCursor["gMaterial"].setObject(mesh->material->shaderObject); - // All the shader parameters and pipeline states have been set up, - // we can now issue a draw call for the mesh. - drawCommandEncoder->drawIndexed(mesh->indexCount, mesh->firstIndex); + // All the shader parameters and pipeline states have been set up, + // we can now issue a draw call for the mesh. + drawCommandEncoder->drawIndexed(mesh->indexCount, mesh->firstIndex); + } } - } - drawCommandEncoder->endEncoding(); - drawCommandBuffer->close(); - gQueue->executeCommandBuffer(drawCommandBuffer); + drawCommandEncoder->endEncoding(); + drawCommandBuffer->close(); + gQueue->executeCommandBuffer(drawCommandBuffer); - if (!isTestMode()) - { - gSwapchain->present(); + if (!isTestMode()) + { + gSwapchain->present(); + } } -} - }; // This macro instantiates an appropriate main function to diff --git a/examples/nv-aftermath-example/main.cpp b/examples/nv-aftermath-example/main.cpp index 9850586c8..67754a911 100644 --- a/examples/nv-aftermath-example/main.cpp +++ b/examples/nv-aftermath-example/main.cpp @@ -1,16 +1,15 @@ // main.cpp -#include "slang.h" -#include "slang-gfx.h" -#include "gfx-util/shader-cursor.h" -#include "tools/platform/window.h" -#include "slang-com-ptr.h" #include "../../source/core/slang-io.h" -#include "source/core/slang-basic.h" -#include "examples/example-base/example-base.h" - #include "GFSDK_Aftermath.h" #include "GFSDK_Aftermath_GpuCrashDump.h" +#include "examples/example-base/example-base.h" +#include "gfx-util/shader-cursor.h" +#include "slang-com-ptr.h" +#include "slang-gfx.h" +#include "slang.h" +#include "source/core/slang-basic.h" +#include "tools/platform/window.h" using namespace gfx; using namespace Slang; @@ -21,10 +20,10 @@ static const ExampleResources resourceBase("nv-aftermath-example"); // // This examples purpose is to show how to use the aftermath SDK to capture // a crash dump. -// +// // * [nsight aftermath](https://developer.nvidia.com/nsight-aftermath) -// -// In addition it uses obfuscation and source maps to allow source level +// +// In addition it uses obfuscation and source maps to allow source level // debugging via aftermath even with obfuscation. // // * [obfuscation](https://github.com/shader-slang/slang/blob/master/docs/user-guide/a1-03-obfuscation.md) @@ -37,29 +36,28 @@ struct Vertex }; static const int kVertexCount = 3; -static const Vertex kVertexData[kVertexCount] = -{ - { { 0, 0, 0.5 }, { 1, 0, 0 } }, - { { 0, 1, 0.5 }, { 0, 0, 1 } }, - { { 1, 0, 0.5 }, { 0, 1, 0 } }, +static const Vertex kVertexData[kVertexCount] = { + {{0, 0, 0.5}, {1, 0, 0}}, + {{0, 1, 0.5}, {0, 0, 1}}, + {{1, 0, 0.5}, {0, 1, 0}}, }; struct AftermathCrashExample : public WindowedAppBase { void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob); - - gfx::Result loadShaderProgram( gfx::IDevice* device, gfx::IShaderProgram** outProgram); - + + gfx::Result loadShaderProgram(gfx::IDevice* device, gfx::IShaderProgram** outProgram); + Slang::Result initialize(); virtual void renderFrame(int frameBufferIndex) override; - + void onAftermathCrash(const void* data, const uint32_t dataSizeInBytes); void onAftermathDebugInfo(const void* pGpuCrashDump, const uint32_t gpuCrashDumpSize); void onAftermathCrashDescription(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription description); - + void onAftermathMarker(const void* pMarker, void** resolvedMarkerData, uint32_t* markerSize); // Create accessors so we don't have to use g prefixed variables. @@ -69,12 +67,15 @@ struct AftermathCrashExample : public WindowedAppBase gfx::ISwapchain* getSwapChain() { return gSwapchain; } gfx::IRenderPassLayout* getRenderPassLayout() { return gRenderPass; } Slang::List>& getFrameBuffers() { return gFramebuffers; } - Slang::List>& getTransientHeaps() { return gTransientHeaps; } + Slang::List>& getTransientHeaps() + { + return gTransientHeaps; + } ComPtr m_pipelineState; ComPtr m_vertexBuffer; - /// A counter such that we can make aftermath dump file names unique + /// A counter such that we can make aftermath dump file names unique std::atomic m_uniqueId = 0; }; @@ -94,13 +95,15 @@ void AftermathCrashExample::onAftermathCrash(const void* data, const uint32_t da // Dump out as a file Slang::StringBuilder filename; filename << "aftermath-dump-" << id << ".bin"; - + File::writeAllBytes(filename, data, dataSizeInBytes); - - //SLANG_BREAKPOINT(0); + + // SLANG_BREAKPOINT(0); } -void AftermathCrashExample::onAftermathDebugInfo(const void* gpuCrashDump, const uint32_t gpuCrashDumpSize) +void AftermathCrashExample::onAftermathDebugInfo( + const void* gpuCrashDump, + const uint32_t gpuCrashDumpSize) { const auto id = m_uniqueId++; @@ -111,41 +114,49 @@ void AftermathCrashExample::onAftermathDebugInfo(const void* gpuCrashDump, const File::writeAllBytes(filename, gpuCrashDump, gpuCrashDumpSize); } -void AftermathCrashExample::onAftermathCrashDescription(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription description) +void AftermathCrashExample::onAftermathCrashDescription( + PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription description) { // Ignore for now } -void AftermathCrashExample::onAftermathMarker(const void* marker, void** resolvedMarkerData, uint32_t* markerSize) +void AftermathCrashExample::onAftermathMarker( + const void* marker, + void** resolvedMarkerData, + uint32_t* markerSize) { // Ignore for now } struct FileSystemEntry { - SlangPathType type; ///< The type of the entry - String path; ///< The path to the entr + SlangPathType type; ///< The type of the entry + String path; ///< The path to the entr }; struct CompileProduct { - String fileName; ///< The filename to write the compile product out to - ComPtr blob; ///< A blob holding the products contents + String fileName; ///< The filename to write the compile product out to + ComPtr blob; ///< A blob holding the products contents }; -/* Currently the mechanism to access the contents of a compilation that might consist of many products is through -representing the contents as a "file system". +/* Currently the mechanism to access the contents of a compilation that might consist of many +products is through representing the contents as a "file system". -The file system is just a somewhat convenient/simple in memory representation of the compilation products. +The file system is just a somewhat convenient/simple in memory representation of the compilation +products. This function transverses the file system and adds everything found into outEntries. */ -static SlangResult _findFileSystemContents(ISlangFileSystemExt* fileSystem, const char* rootPath, List& outEntries) +static SlangResult _findFileSystemContents( + ISlangFileSystemExt* fileSystem, + const char* rootPath, + List& outEntries) { { SlangPathType type; SLANG_RETURN_ON_FAIL(fileSystem->getPathType(rootPath, &type)); - outEntries.add(FileSystemEntry{ type, rootPath }); + outEntries.add(FileSystemEntry{type, rootPath}); } // A context used to hold state, when using enumeratePathContents @@ -162,16 +173,18 @@ static SlangResult _findFileSystemContents(ISlangFileSystemExt* fileSystem, cons // If it's a directory we want to traverse it's contents if (entry.type == SLANG_PATH_TYPE_DIRECTORY) { - Context context{outEntries, entry.path }; + Context context{outEntries, entry.path}; - fileSystem->enumeratePathContents(entry.path.getBuffer(), - [](SlangPathType pathType, const char* name, void* userData) -> void { + fileSystem->enumeratePathContents( + entry.path.getBuffer(), + [](SlangPathType pathType, const char* name, void* userData) -> void + { Context* context = reinterpret_cast(userData); const String path = Path::simplify(Path::combine(context->path, name)); context->entries.add({pathType, path}); - }, + }, &context); } } @@ -179,14 +192,18 @@ static SlangResult _findFileSystemContents(ISlangFileSystemExt* fileSystem, cons return SLANG_OK; } -/* This function takes a compile results file system, and finds items that should be written out. +/* This function takes a compile results file system, and finds items that should be written out. -This is somewhat complicated because the names of products from different compilations might have the same names. -So a "prefix" is passed in, and for files that don't have unique names, they are uniqified via the prefix. +This is somewhat complicated because the names of products from different compilations might have +the same names. So a "prefix" is passed in, and for files that don't have unique names, they are +uniqified via the prefix. -The same product may appear in multiple compilations, for example obfuscated source maps so a product is not added -if there is already a product with the same name */ -static SlangResult _addCompileProducts(ISlangFileSystemExt* fileSystem, const char* prefix, List& ioProducts) +The same product may appear in multiple compilations, for example obfuscated source maps so a +product is not added if there is already a product with the same name */ +static SlangResult _addCompileProducts( + ISlangFileSystemExt* fileSystem, + const char* prefix, + List& ioProducts) { List fileSystemEntries; SLANG_RETURN_ON_FAIL(_findFileSystemContents(fileSystem, ".", fileSystemEntries)); @@ -201,17 +218,18 @@ static SlangResult _addCompileProducts(ISlangFileSystemExt* fileSystem, const ch const auto ext = Path::getPathExt(fileSystemEntry.path); String outFileName; - + // Some filenames need special handling, and their names are already unique - // Others will be the same between differen fileSystem that represent the - // compilation products. + // Others will be the same between differen fileSystem that represent the + // compilation products. // // Source maps that are obfuscated are unique. { String inFileName = Path::getFileNameWithoutExt(fileSystemEntry.path); - + // If it's an obfuscated source map, it's name is already unique (it includes the hash) - const bool isUniqueName = (ext == toSlice("map") && inFileName.endsWith(toSlice("-obfuscated"))); + const bool isUniqueName = + (ext == toSlice("map") && inFileName.endsWith(toSlice("-obfuscated"))); StringBuilder buf; // If it's not a uniquename make it unique via the prefix @@ -224,20 +242,21 @@ static SlangResult _addCompileProducts(ISlangFileSystemExt* fileSystem, const ch buf << inFileName << "." << ext; outFileName = buf; } - + // If we have an output filename if (outFileName.getLength()) { // And that filename isn't already used - if (ioProducts.findFirstIndex([&](const CompileProduct& product) -> bool { - return product.fileName == outFileName; - }) < 0) + if (ioProducts.findFirstIndex( + [&](const CompileProduct& product) -> bool + { return product.fileName == outFileName; }) < 0) { ComPtr blob; - SLANG_RETURN_ON_FAIL(fileSystem->loadFile(fileSystemEntry.path.getBuffer(), blob.writeRef())); + SLANG_RETURN_ON_FAIL( + fileSystem->loadFile(fileSystemEntry.path.getBuffer(), blob.writeRef())); // Add to the results - ioProducts.add(CompileProduct{ outFileName, blob }); + ioProducts.add(CompileProduct{outFileName, blob}); } } } @@ -252,11 +271,11 @@ gfx::Result AftermathCrashExample::loadShaderProgram( ComPtr slangSession; slangSession = device->getSlangSession(); - // This is a little bit of a work around. - // + // This is a little bit of a work around. + // // We want to set some options that are only available // via processCommandLineArguments, but we need a request to be able to set them up - // The setting actually sets the parameters on the Linkage, so they will be used for the later + // The setting actually sets the parameters on the Linkage, so they will be used for the later // actual compilation { ComPtr request; @@ -264,20 +283,20 @@ gfx::Result AftermathCrashExample::loadShaderProgram( SLANG_RETURN_ON_FAIL(slangSession->createCompileRequest(request.writeRef())); // Turn on obfuscation - // + // // Turns on source map as the line directive, this will lead to an "emit source map" // and no #line directives in generated source. // // It isn't necessary to use the "source-map" line directive mode, and just use // #line directives, and have source locations to obfuscated source file directly embedded. - // + // // To do this replace the line below with // // ``` // const char* args[] = { "-obfuscate" }; // ``` - const char* args[] = { "-obfuscate", "-line-directive-mode", "source-map" }; - + const char* args[] = {"-obfuscate", "-line-directive-mode", "source-map"}; + request->processCommandLineArguments(args, SLANG_COUNT_OF(args)); // Enable debug info @@ -296,7 +315,8 @@ gfx::Result AftermathCrashExample::loadShaderProgram( SLANG_RETURN_ON_FAIL(module->findEntryPointByName("vertexMain", vertexEntryPoint.writeRef())); // ComPtr fragmentEntryPoint; - SLANG_RETURN_ON_FAIL(module->findEntryPointByName("fragmentMain", fragmentEntryPoint.writeRef())); + SLANG_RETURN_ON_FAIL( + module->findEntryPointByName("fragmentMain", fragmentEntryPoint.writeRef())); // At this point we have a few different Slang API objects that represent // pieces of our code: `module`, `vertexEntryPoint`, and `fragmentEntryPoint`. @@ -348,36 +368,53 @@ gfx::Result AftermathCrashExample::loadShaderProgram( ComPtr code; ComPtr diagnostics; - SLANG_RETURN_ON_FAIL(linkedProgram->getEntryPointCode(vertexEntryPointIndex, targetIndex, code.writeRef(), diagnostics.writeRef())); - SLANG_RETURN_ON_FAIL(linkedProgram->getEntryPointCode(fragmentEntryPointIndex, targetIndex, code.writeRef(), diagnostics.writeRef())); + SLANG_RETURN_ON_FAIL(linkedProgram->getEntryPointCode( + vertexEntryPointIndex, + targetIndex, + code.writeRef(), + diagnostics.writeRef())); + SLANG_RETURN_ON_FAIL(linkedProgram->getEntryPointCode( + fragmentEntryPointIndex, + targetIndex, + code.writeRef(), + diagnostics.writeRef())); } { - // We want to find all the compilation products. In particular we want to get the emit source map, and the obfuscated - // source maps + // We want to find all the compilation products. In particular we want to get the emit + // source map, and the obfuscated source maps List compileProducts; - // The current mechanism for getting access to compilation products other than result blob/diagnostics is to - // return it as a compilation result "file system". + // The current mechanism for getting access to compilation products other than result + // blob/diagnostics is to return it as a compilation result "file system". ComPtr vertexFileSystem; - SLANG_RETURN_ON_FAIL(linkedProgram->getResultAsFileSystem(vertexEntryPointIndex, targetIndex, vertexFileSystem.writeRef())); + SLANG_RETURN_ON_FAIL(linkedProgram->getResultAsFileSystem( + vertexEntryPointIndex, + targetIndex, + vertexFileSystem.writeRef())); ComPtr fragmentFileSystem; - SLANG_RETURN_ON_FAIL(linkedProgram->getResultAsFileSystem(fragmentEntryPointIndex, targetIndex, fragmentFileSystem.writeRef())); + SLANG_RETURN_ON_FAIL(linkedProgram->getResultAsFileSystem( + fragmentEntryPointIndex, + targetIndex, + fragmentFileSystem.writeRef())); // Add the contents of the compile result file systems into compileProducts - // Some products might appear in both file systems, so compileProducts is just the unique products. - // Additionally because some products may have the same name, we pass in a "prefix" to make the products name - // unique. + // Some products might appear in both file systems, so compileProducts is just the unique + // products. Additionally because some products may have the same name, we pass in a + // "prefix" to make the products name unique. SLANG_RETURN_ON_FAIL(_addCompileProducts(vertexFileSystem, "vertex", compileProducts)); SLANG_RETURN_ON_FAIL(_addCompileProducts(fragmentFileSystem, "fragment", compileProducts)); - // Now write all of the products out + // Now write all of the products out for (const auto& product : compileProducts) { - SLANG_RETURN_ON_FAIL(File::writeAllBytes(product.fileName, product.blob->getBufferPointer(), product.blob->getBufferSize())); + SLANG_RETURN_ON_FAIL(File::writeAllBytes( + product.fileName, + product.blob->getBufferPointer(), + product.blob->getBufferSize())); } } @@ -393,36 +430,53 @@ gfx::Result AftermathCrashExample::loadShaderProgram( return SLANG_OK; } -static void GFSDK_AFTERMATH_CALL _crashCallback(const void* gpuCrashDump, const uint32_t gpuCrashDumpSize, void* userData) +static void GFSDK_AFTERMATH_CALL +_crashCallback(const void* gpuCrashDump, const uint32_t gpuCrashDumpSize, void* userData) { - reinterpret_cast(userData)->onAftermathCrash(gpuCrashDump, gpuCrashDumpSize); + reinterpret_cast(userData)->onAftermathCrash( + gpuCrashDump, + gpuCrashDumpSize); } -static void GFSDK_AFTERMATH_CALL _debugInfoCallback(const void* gpuCrashDump, const uint32_t gpuCrashDumpSize, void* userData) +static void GFSDK_AFTERMATH_CALL +_debugInfoCallback(const void* gpuCrashDump, const uint32_t gpuCrashDumpSize, void* userData) { - reinterpret_cast(userData)->onAftermathDebugInfo(gpuCrashDump, gpuCrashDumpSize); + reinterpret_cast(userData)->onAftermathDebugInfo( + gpuCrashDump, + gpuCrashDumpSize); } -static void GFSDK_AFTERMATH_CALL _crashDescriptionCallback(PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription, void* userData) +static void GFSDK_AFTERMATH_CALL _crashDescriptionCallback( + PFN_GFSDK_Aftermath_AddGpuCrashDumpDescription addDescription, + void* userData) { reinterpret_cast(userData)->onAftermathCrashDescription(addDescription); } -static void GFSDK_AFTERMATH_CALL _markerCallback(const void* marker, void* pUserData, void** resolvedMarkerData, uint32_t* markerSize) +static void GFSDK_AFTERMATH_CALL _markerCallback( + const void* marker, + void* pUserData, + void** resolvedMarkerData, + uint32_t* markerSize) { - reinterpret_cast(pUserData)->onAftermathMarker(marker, resolvedMarkerData, markerSize); + reinterpret_cast(pUserData)->onAftermathMarker( + marker, + resolvedMarkerData, + markerSize); } Slang::Result AftermathCrashExample::initialize() { // Defer shader debug information callbacks until an actual GPU crash dump // is generated. Increases memory footprint. - const uint32_t aftermathFeatureFlags = GFSDK_Aftermath_GpuCrashDumpFeatureFlags_DeferDebugInfoCallbacks; + const uint32_t aftermathFeatureFlags = + GFSDK_Aftermath_GpuCrashDumpFeatureFlags_DeferDebugInfoCallbacks; // As per docs must be called before any device is created GFSDK_Aftermath_EnableGpuCrashDumps( GFSDK_Aftermath_Version_API, - GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags_DX | GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags_Vulkan, + GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags_DX | + GFSDK_Aftermath_GpuCrashDumpWatchedApiFlags_Vulkan, aftermathFeatureFlags, _crashCallback, _debugInfoCallback, @@ -431,14 +485,14 @@ Slang::Result AftermathCrashExample::initialize() this); // Set to a specific render API as needed. Valid values are... - // + // // * gfx::DeviceType::Default // * gfx::DeviceType::Vulkan // * gfx::DeviceType::DirectX12 // * gfx::DeviceType::DirectX11 const gfx::DeviceType deviceType = gfx::DeviceType::Default; - + initializeBase("aftermath-crash-example", 1024, 768, deviceType); auto device = getDevice(); @@ -449,14 +503,12 @@ Slang::Result AftermathCrashExample::initialize() // First, we create an input layout: // InputElementDesc inputElements[] = { - { "POSITION", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, position) }, - { "COLOR", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, color) }, + {"POSITION", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, position)}, + {"COLOR", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, color)}, }; - auto inputLayout = gDevice->createInputLayout( - sizeof(Vertex), - &inputElements[0], - 2); - if (!inputLayout) return SLANG_FAIL; + auto inputLayout = gDevice->createInputLayout(sizeof(Vertex), &inputElements[0], 2); + if (!inputLayout) + return SLANG_FAIL; // Next we allocate a vertex buffer for our pre-initialized // vertex data. @@ -466,7 +518,8 @@ Slang::Result AftermathCrashExample::initialize() vertexBufferDesc.sizeInBytes = kVertexCount * sizeof(Vertex); vertexBufferDesc.defaultState = ResourceState::VertexBuffer; m_vertexBuffer = device->createBufferResource(vertexBufferDesc, &kVertexData[0]); - if (!m_vertexBuffer) return SLANG_FAIL; + if (!m_vertexBuffer) + return SLANG_FAIL; // Now we will use our `loadShaderProgram` function to load // the code from `shaders.slang` into the graphics API. @@ -490,10 +543,12 @@ Slang::Result AftermathCrashExample::initialize() return SLANG_OK; } -void AftermathCrashExample::renderFrame(int frameBufferIndex) +void AftermathCrashExample::renderFrame(int frameBufferIndex) { - ComPtr commandBuffer = getTransientHeaps()[frameBufferIndex]->createCommandBuffer(); - auto renderEncoder = commandBuffer->encodeRenderCommands(gRenderPass, getFrameBuffers()[frameBufferIndex]); + ComPtr commandBuffer = + getTransientHeaps()[frameBufferIndex]->createCommandBuffer(); + auto renderEncoder = + commandBuffer->encodeRenderCommands(gRenderPass, getFrameBuffers()[frameBufferIndex]); gfx::Viewport viewport = {}; viewport.maxZ = 1.0f; @@ -508,9 +563,10 @@ void AftermathCrashExample::renderFrame(int frameBufferIndex) ShaderCursor rootCursor(rootObject); rootCursor["Uniforms"]["modelViewProjection"].setData( - deviceInfo.identityProjectionMatrix, sizeof(float) * 16); + deviceInfo.identityProjectionMatrix, + sizeof(float) * 16); - // We are going to extra efforts to create a shader that we know will time + // We are going to extra efforts to create a shader that we know will time // out because we *want* a GPU "crash", such we can capture via nsight aftermath. // The failCount is just a number that is large enought to make things take too long. int32_t failCount = 0x3fffffff; diff --git a/examples/platform-test/main.cpp b/examples/platform-test/main.cpp index f20a5a716..daa9bbc4b 100644 --- a/examples/platform-test/main.cpp +++ b/examples/platform-test/main.cpp @@ -1,6 +1,6 @@ +#include "examples/example-base/example-base.h" #include "slang.h" #include "tools/platform/window.h" -#include "examples/example-base/example-base.h" using namespace gfx; using namespace Slang; @@ -8,93 +8,105 @@ using namespace Slang; struct PlatformTest : public WindowedAppBase { -void onSizeChanged() -{ - printf("onSizeChanged\n"); -} - -void onFocus() -{ - printf("onFocus\n"); -} - -void onLostFocus() -{ - printf("onLostFocus\n"); -} - -void onKeyDown(platform::KeyEventArgs args) -{ - printf("onKeyDown(key=0x%02x, buttons=0x%02x)\n", (uint32_t)args.key, args.buttons); -} - -void onKeyUp(platform::KeyEventArgs args) -{ - printf("okKeyUp(key=0x%02x, buttons=0x%02x)\n", (uint32_t)args.key, args.buttons); -} - -void onKeyPress(platform::KeyEventArgs args) -{ - printf("onKeyPress(keyChar=0x%02x)\n", args.keyChar); -} - -void onMouseMove(platform::MouseEventArgs args) -{ - printf("onMouseMove(x=%d, y=%d, delta=%d, buttons=0x%02x\n", args.x, args.y, args.delta, args.buttons); -} - -void onMouseDown(platform::MouseEventArgs args) -{ - printf("onMouseDown(x=%d, y=%d, delta=%d, buttons=0x%02x\n", args.x, args.y, args.delta, args.buttons); -} - -void onMouseUp(platform::MouseEventArgs args) -{ - printf("onMouseUp(x=%d, y=%d, delta=%d, buttons=0x%02x\n", args.x, args.y, args.delta, args.buttons); -} - -void onMouseWheel(platform::MouseEventArgs args) -{ - printf("onMouseWheel(x=%d, y=%d, delta=%d, buttons=0x%02x\n", args.x, args.y, args.delta, args.buttons); -} - -Slang::Result initialize() -{ - initializeBase("platform-test", 1024, 768); - - gWindow->events.sizeChanged = [this]() { onSizeChanged(); }; - gWindow->events.focus = [this]() { onFocus(); }; - gWindow->events.lostFocus = [this]() { onLostFocus(); }; - gWindow->events.keyDown = [this](const platform::KeyEventArgs& e) { onKeyDown(e); }; - gWindow->events.keyUp = [this](const platform::KeyEventArgs& e) { onKeyUp(e); }; - gWindow->events.keyPress = [this](const platform::KeyEventArgs& e) { onKeyPress(e); }; - gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { onMouseMove(e); }; - gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { onMouseDown(e); }; - gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { onMouseUp(e); }; - gWindow->events.mouseWheel = [this](const platform::MouseEventArgs& e) { onMouseWheel(e); }; - - return SLANG_OK; -} - -virtual void renderFrame(int frameBufferIndex) override -{ - ComPtr commandBuffer = gTransientHeaps[frameBufferIndex]->createCommandBuffer(); - - auto renderEncoder = commandBuffer->encodeRenderCommands(gRenderPass, gFramebuffers[frameBufferIndex]); - - gfx::Viewport viewport = {}; - viewport.maxZ = 1.0f; - viewport.extentX = (float)windowWidth; - viewport.extentY = (float)windowHeight; - renderEncoder->setViewportAndScissor(viewport); - - renderEncoder->endEncoding(); - commandBuffer->close(); - gQueue->executeCommandBuffer(commandBuffer); - - gSwapchain->present(); -} - + void onSizeChanged() { printf("onSizeChanged\n"); } + + void onFocus() { printf("onFocus\n"); } + + void onLostFocus() { printf("onLostFocus\n"); } + + void onKeyDown(platform::KeyEventArgs args) + { + printf("onKeyDown(key=0x%02x, buttons=0x%02x)\n", (uint32_t)args.key, args.buttons); + } + + void onKeyUp(platform::KeyEventArgs args) + { + printf("okKeyUp(key=0x%02x, buttons=0x%02x)\n", (uint32_t)args.key, args.buttons); + } + + void onKeyPress(platform::KeyEventArgs args) + { + printf("onKeyPress(keyChar=0x%02x)\n", args.keyChar); + } + + void onMouseMove(platform::MouseEventArgs args) + { + printf( + "onMouseMove(x=%d, y=%d, delta=%d, buttons=0x%02x\n", + args.x, + args.y, + args.delta, + args.buttons); + } + + void onMouseDown(platform::MouseEventArgs args) + { + printf( + "onMouseDown(x=%d, y=%d, delta=%d, buttons=0x%02x\n", + args.x, + args.y, + args.delta, + args.buttons); + } + + void onMouseUp(platform::MouseEventArgs args) + { + printf( + "onMouseUp(x=%d, y=%d, delta=%d, buttons=0x%02x\n", + args.x, + args.y, + args.delta, + args.buttons); + } + + void onMouseWheel(platform::MouseEventArgs args) + { + printf( + "onMouseWheel(x=%d, y=%d, delta=%d, buttons=0x%02x\n", + args.x, + args.y, + args.delta, + args.buttons); + } + + Slang::Result initialize() + { + initializeBase("platform-test", 1024, 768); + + gWindow->events.sizeChanged = [this]() { onSizeChanged(); }; + gWindow->events.focus = [this]() { onFocus(); }; + gWindow->events.lostFocus = [this]() { onLostFocus(); }; + gWindow->events.keyDown = [this](const platform::KeyEventArgs& e) { onKeyDown(e); }; + gWindow->events.keyUp = [this](const platform::KeyEventArgs& e) { onKeyUp(e); }; + gWindow->events.keyPress = [this](const platform::KeyEventArgs& e) { onKeyPress(e); }; + gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { onMouseMove(e); }; + gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { onMouseDown(e); }; + gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { onMouseUp(e); }; + gWindow->events.mouseWheel = [this](const platform::MouseEventArgs& e) { onMouseWheel(e); }; + + return SLANG_OK; + } + + virtual void renderFrame(int frameBufferIndex) override + { + ComPtr commandBuffer = + gTransientHeaps[frameBufferIndex]->createCommandBuffer(); + + auto renderEncoder = + commandBuffer->encodeRenderCommands(gRenderPass, gFramebuffers[frameBufferIndex]); + + gfx::Viewport viewport = {}; + viewport.maxZ = 1.0f; + viewport.extentX = (float)windowWidth; + viewport.extentY = (float)windowHeight; + renderEncoder->setViewportAndScissor(viewport); + + renderEncoder->endEncoding(); + commandBuffer->close(); + gQueue->executeCommandBuffer(commandBuffer); + + gSwapchain->present(); + } }; // This macro instantiates an appropriate main function to diff --git a/examples/ray-tracing-pipeline/main.cpp b/examples/ray-tracing-pipeline/main.cpp index 562eca4dc..f5ad03e1b 100644 --- a/examples/ray-tracing-pipeline/main.cpp +++ b/examples/ray-tracing-pipeline/main.cpp @@ -3,14 +3,14 @@ // This file implements an example of hardware ray-tracing using // Slang shaders and the `gfx` graphics API. -#include "slang.h" -#include "slang-gfx.h" +#include "examples/example-base/example-base.h" #include "gfx-util/shader-cursor.h" -#include "tools/platform/window.h" -#include "tools/platform/vector-math.h" #include "slang-com-ptr.h" +#include "slang-gfx.h" +#include "slang.h" #include "source/core/slang-basic.h" -#include "examples/example-base/example-base.h" +#include "tools/platform/vector-math.h" +#include "tools/platform/window.h" using namespace gfx; using namespace Slang; @@ -36,8 +36,7 @@ struct Vertex // Define geometry data for our test scene. // The scene contains a floor plane, and a cube placed on top of it at the center. static const int kVertexCount = 24; -static const Vertex kVertexData[kVertexCount] = -{ +static const Vertex kVertexData[kVertexCount] = { // Floor plane {{-100.0f, 0, 100.0f}}, {{100.0f, 0, 100.0f}}, @@ -70,15 +69,9 @@ static const Vertex kVertexData[kVertexCount] = {{1.0f, 0.0, -1.0f}}, }; static const int kIndexCount = 36; -static const int kIndexData[kIndexCount] = -{ - 0, 1, 2, 0, 2, 3, - 4, 5, 6, 4, 6, 7, - 8, 9, 10, 8, 10, 11, - 12, 13, 14, 12, 14, 15, - 16, 17, 18, 16, 18, 19, - 20, 21, 22, 20, 22, 23 -}; +static const int kIndexData[kIndexCount] = {0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, + 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, + 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23}; struct Primitive { @@ -86,8 +79,7 @@ struct Primitive float color[4]; }; static const int kPrimitiveCount = 12; -static const Primitive kPrimitiveData[kPrimitiveCount] = -{ +static const Primitive kPrimitiveData[kPrimitiveCount] = { {{0.0f, 1.0f, 0.0f, 0.0f}, {0.75f, 0.8f, 0.85f, 1.0f}}, {{0.0f, 1.0f, 0.0f, 0.0f}, {0.75f, 0.8f, 0.85f, 1.0f}}, {{0.0f, 1.0f, 0.0f, 0.0f}, {0.95f, 0.85f, 0.05f, 1.0f}}, @@ -134,559 +126,575 @@ struct RayTracing : public WindowedAppBase { -Uniforms gUniforms = {}; + Uniforms gUniforms = {}; -// Many Slang API functions return detailed diagnostic information -// (error messages, warnings, etc.) as a "blob" of data, or return -// a null blob pointer instead if there were no issues. -// -// For convenience, we define a subroutine that will dump the information -// in a diagnostic blob if one is produced, and skip it otherwise. -// -void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob) -{ - if( diagnosticsBlob != nullptr ) + // Many Slang API functions return detailed diagnostic information + // (error messages, warnings, etc.) as a "blob" of data, or return + // a null blob pointer instead if there were no issues. + // + // For convenience, we define a subroutine that will dump the information + // in a diagnostic blob if one is produced, and skip it otherwise. + // + void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob) { - printf("%s", (const char*) diagnosticsBlob->getBufferPointer()); + if (diagnosticsBlob != nullptr) + { + printf("%s", (const char*)diagnosticsBlob->getBufferPointer()); #ifdef _WIN32 - _Win32OutputDebugString((const char*)diagnosticsBlob->getBufferPointer()); + _Win32OutputDebugString((const char*)diagnosticsBlob->getBufferPointer()); #endif + } } -} -// Load and compile shader code from souce. -gfx::Result loadShaderProgram( - gfx::IDevice* device, bool isRayTracingPipeline, gfx::IShaderProgram** outProgram) -{ - ComPtr slangSession; - slangSession = device->getSlangSession(); - - ComPtr diagnosticsBlob; - Slang::String path = resourceBase.resolveResource("shaders.slang"); - slang::IModule* module = slangSession->loadModule(path.getBuffer(), diagnosticsBlob.writeRef()); - diagnoseIfNeeded(diagnosticsBlob); - if(!module) - return SLANG_FAIL; - - Slang::List componentTypes; - componentTypes.add(module); - if (isRayTracingPipeline) - { - ComPtr entryPoint; - SLANG_RETURN_ON_FAIL(module->findEntryPointByName("rayGenShader", entryPoint.writeRef())); - componentTypes.add(entryPoint); - SLANG_RETURN_ON_FAIL(module->findEntryPointByName("missShader", entryPoint.writeRef())); - componentTypes.add(entryPoint); - SLANG_RETURN_ON_FAIL( - module->findEntryPointByName("closestHitShader", entryPoint.writeRef())); - componentTypes.add(entryPoint); - SLANG_RETURN_ON_FAIL( - module->findEntryPointByName("shadowRayHitShader", entryPoint.writeRef())); - componentTypes.add(entryPoint); - } - else + // Load and compile shader code from souce. + gfx::Result loadShaderProgram( + gfx::IDevice* device, + bool isRayTracingPipeline, + gfx::IShaderProgram** outProgram) { - ComPtr entryPoint; - SLANG_RETURN_ON_FAIL(module->findEntryPointByName("vertexMain", entryPoint.writeRef())); - componentTypes.add(entryPoint); - SLANG_RETURN_ON_FAIL(module->findEntryPointByName("fragmentMain", entryPoint.writeRef())); - componentTypes.add(entryPoint); - } - - ComPtr linkedProgram; - SlangResult result = slangSession->createCompositeComponentType( - componentTypes.getBuffer(), - componentTypes.getCount(), - linkedProgram.writeRef(), - diagnosticsBlob.writeRef()); - diagnoseIfNeeded(diagnosticsBlob); - SLANG_RETURN_ON_FAIL(result); + ComPtr slangSession; + slangSession = device->getSlangSession(); + + ComPtr diagnosticsBlob; + Slang::String path = resourceBase.resolveResource("shaders.slang"); + slang::IModule* module = + slangSession->loadModule(path.getBuffer(), diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + if (!module) + return SLANG_FAIL; - if (isTestMode()) - { - printEntrypointHashes(componentTypes.getCount() - 1, 1, linkedProgram); + Slang::List componentTypes; + componentTypes.add(module); + if (isRayTracingPipeline) + { + ComPtr entryPoint; + SLANG_RETURN_ON_FAIL( + module->findEntryPointByName("rayGenShader", entryPoint.writeRef())); + componentTypes.add(entryPoint); + SLANG_RETURN_ON_FAIL(module->findEntryPointByName("missShader", entryPoint.writeRef())); + componentTypes.add(entryPoint); + SLANG_RETURN_ON_FAIL( + module->findEntryPointByName("closestHitShader", entryPoint.writeRef())); + componentTypes.add(entryPoint); + SLANG_RETURN_ON_FAIL( + module->findEntryPointByName("shadowRayHitShader", entryPoint.writeRef())); + componentTypes.add(entryPoint); + } + else + { + ComPtr entryPoint; + SLANG_RETURN_ON_FAIL(module->findEntryPointByName("vertexMain", entryPoint.writeRef())); + componentTypes.add(entryPoint); + SLANG_RETURN_ON_FAIL( + module->findEntryPointByName("fragmentMain", entryPoint.writeRef())); + componentTypes.add(entryPoint); + } + + ComPtr linkedProgram; + SlangResult result = slangSession->createCompositeComponentType( + componentTypes.getBuffer(), + componentTypes.getCount(), + linkedProgram.writeRef(), + diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + SLANG_RETURN_ON_FAIL(result); + + if (isTestMode()) + { + printEntrypointHashes(componentTypes.getCount() - 1, 1, linkedProgram); + } + + gfx::IShaderProgram::Desc programDesc = {}; + programDesc.slangGlobalScope = linkedProgram; + SLANG_RETURN_ON_FAIL(device->createProgram(programDesc, outProgram)); + + return SLANG_OK; } - gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangGlobalScope = linkedProgram; - SLANG_RETURN_ON_FAIL(device->createProgram(programDesc, outProgram)); - - return SLANG_OK; -} - -ComPtr gPresentPipelineState; -ComPtr gRenderPipelineState; -ComPtr gFullScreenVertexBuffer; -ComPtr gVertexBuffer; -ComPtr gIndexBuffer; -ComPtr gPrimitiveBuffer; -ComPtr gTransformBuffer; -ComPtr gPrimitiveBufferSRV; -ComPtr gInstanceBuffer; -ComPtr gBLASBuffer; -ComPtr gBLAS; -ComPtr gTLASBuffer; -ComPtr gTLAS; -ComPtr gResultTexture; -ComPtr gResultTextureUAV; -ComPtr gShaderTable; - -uint64_t lastTime = 0; - -// glm::vec3 lightDir = normalize(glm::vec3(10, 10, 10)); -// glm::vec3 lightColor = glm::vec3(1, 1, 1); - -glm::vec3 cameraPosition = glm::vec3(-2.53f, 2.72f, 4.3f); -float cameraOrientationAngles[2] = {-0.475f, -0.35f}; // Spherical angles (theta, phi). - -float translationScale = 0.5f; -float rotationScale = 0.01f; - -// In order to control camera movement, we will -// use good old WASD -bool wPressed = false; -bool aPressed = false; -bool sPressed = false; -bool dPressed = false; - -bool isMouseDown = false; -float lastMouseX = 0.0f; -float lastMouseY = 0.0f; - -void setKeyState(platform::KeyCode key, bool state) -{ - switch (key) + ComPtr gPresentPipelineState; + ComPtr gRenderPipelineState; + ComPtr gFullScreenVertexBuffer; + ComPtr gVertexBuffer; + ComPtr gIndexBuffer; + ComPtr gPrimitiveBuffer; + ComPtr gTransformBuffer; + ComPtr gPrimitiveBufferSRV; + ComPtr gInstanceBuffer; + ComPtr gBLASBuffer; + ComPtr gBLAS; + ComPtr gTLASBuffer; + ComPtr gTLAS; + ComPtr gResultTexture; + ComPtr gResultTextureUAV; + ComPtr gShaderTable; + + uint64_t lastTime = 0; + + // glm::vec3 lightDir = normalize(glm::vec3(10, 10, 10)); + // glm::vec3 lightColor = glm::vec3(1, 1, 1); + + glm::vec3 cameraPosition = glm::vec3(-2.53f, 2.72f, 4.3f); + float cameraOrientationAngles[2] = {-0.475f, -0.35f}; // Spherical angles (theta, phi). + + float translationScale = 0.5f; + float rotationScale = 0.01f; + + // In order to control camera movement, we will + // use good old WASD + bool wPressed = false; + bool aPressed = false; + bool sPressed = false; + bool dPressed = false; + + bool isMouseDown = false; + float lastMouseX = 0.0f; + float lastMouseY = 0.0f; + + void setKeyState(platform::KeyCode key, bool state) { - default: - break; - case platform::KeyCode::W: - wPressed = state; - break; - case platform::KeyCode::A: - aPressed = state; - break; - case platform::KeyCode::S: - sPressed = state; - break; - case platform::KeyCode::D: - dPressed = state; - break; + switch (key) + { + default: break; + case platform::KeyCode::W: wPressed = state; break; + case platform::KeyCode::A: aPressed = state; break; + case platform::KeyCode::S: sPressed = state; break; + case platform::KeyCode::D: dPressed = state; break; + } } -} -void onKeyDown(platform::KeyEventArgs args) { setKeyState(args.key, true); } -void onKeyUp(platform::KeyEventArgs args) { setKeyState(args.key, false); } + void onKeyDown(platform::KeyEventArgs args) { setKeyState(args.key, true); } + void onKeyUp(platform::KeyEventArgs args) { setKeyState(args.key, false); } -void onMouseDown(platform::MouseEventArgs args) -{ - isMouseDown = true; - lastMouseX = (float)args.x; - lastMouseY = (float)args.y; -} - -void onMouseMove(platform::MouseEventArgs args) -{ - if (isMouseDown) + void onMouseDown(platform::MouseEventArgs args) { - float deltaX = args.x - lastMouseX; - float deltaY = args.y - lastMouseY; - - cameraOrientationAngles[0] += -deltaX * rotationScale; - cameraOrientationAngles[1] += -deltaY * rotationScale; + isMouseDown = true; lastMouseX = (float)args.x; lastMouseY = (float)args.y; } -} -void onMouseUp(platform::MouseEventArgs args) { isMouseDown = false; } -Slang::Result initialize() -{ - initializeBase("Ray Tracing Pipeline", 1024, 768); - if (!isTestMode()) + void onMouseMove(platform::MouseEventArgs args) { - gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { onMouseMove(e); }; - gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { onMouseUp(e); }; - gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { onMouseDown(e); }; - gWindow->events.keyDown = [this](const platform::KeyEventArgs& e) { onKeyDown(e); }; - gWindow->events.keyUp = [this](const platform::KeyEventArgs& e) { onKeyUp(e); }; + if (isMouseDown) + { + float deltaX = args.x - lastMouseX; + float deltaY = args.y - lastMouseY; + + cameraOrientationAngles[0] += -deltaX * rotationScale; + cameraOrientationAngles[1] += -deltaY * rotationScale; + lastMouseX = (float)args.x; + lastMouseY = (float)args.y; + } } + void onMouseUp(platform::MouseEventArgs args) { isMouseDown = false; } - IBufferResource::Desc vertexBufferDesc; - vertexBufferDesc.type = IResource::Type::Buffer; - vertexBufferDesc.sizeInBytes = kVertexCount * sizeof(Vertex); - vertexBufferDesc.defaultState = ResourceState::ShaderResource; - gVertexBuffer = gDevice->createBufferResource(vertexBufferDesc, &kVertexData[0]); - if(!gVertexBuffer) return SLANG_FAIL; - - IBufferResource::Desc indexBufferDesc; - indexBufferDesc.type = IResource::Type::Buffer; - indexBufferDesc.sizeInBytes = kIndexCount * sizeof(int32_t); - indexBufferDesc.defaultState = ResourceState::ShaderResource; - gIndexBuffer = gDevice->createBufferResource(indexBufferDesc, &kIndexData[0]); - if (!gIndexBuffer) - return SLANG_FAIL; - - IBufferResource::Desc primitiveBufferDesc; - primitiveBufferDesc.type = IResource::Type::Buffer; - primitiveBufferDesc.sizeInBytes = kPrimitiveCount * sizeof(Primitive); - primitiveBufferDesc.elementSize = sizeof(Primitive); - primitiveBufferDesc.defaultState = ResourceState::ShaderResource; - gPrimitiveBuffer = gDevice->createBufferResource(primitiveBufferDesc, &kPrimitiveData[0]); - if (!gPrimitiveBuffer) - return SLANG_FAIL; - - IResourceView::Desc primitiveSRVDesc = {}; - primitiveSRVDesc.format = Format::Unknown; - primitiveSRVDesc.type = IResourceView::Type::ShaderResource; - gPrimitiveBufferSRV = gDevice->createBufferView(gPrimitiveBuffer, nullptr, primitiveSRVDesc); - - IBufferResource::Desc transformBufferDesc; - transformBufferDesc.type = IResource::Type::Buffer; - transformBufferDesc.sizeInBytes = sizeof(float) * 12; - transformBufferDesc.defaultState = ResourceState::ShaderResource; - float transformData[12] = { - 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}; - gTransformBuffer = gDevice->createBufferResource(transformBufferDesc, &transformData); - if (!gTransformBuffer) - return SLANG_FAIL; - // Build bottom level acceleration structure. + Slang::Result initialize() { - IAccelerationStructure::BuildInputs accelerationStructureBuildInputs; - IAccelerationStructure::PrebuildInfo accelerationStructurePrebuildInfo; - accelerationStructureBuildInputs.descCount = 1; - accelerationStructureBuildInputs.kind = IAccelerationStructure::Kind::BottomLevel; - accelerationStructureBuildInputs.flags = - IAccelerationStructure::BuildFlags::AllowCompaction; - IAccelerationStructure::GeometryDesc geomDesc; - geomDesc.flags = IAccelerationStructure::GeometryFlags::Opaque; - geomDesc.type = IAccelerationStructure::GeometryType::Triangles; - geomDesc.content.triangles.indexCount = kIndexCount; - geomDesc.content.triangles.indexData = gIndexBuffer->getDeviceAddress(); - geomDesc.content.triangles.indexFormat = Format::R32_UINT; - geomDesc.content.triangles.vertexCount = kVertexCount; - geomDesc.content.triangles.vertexData = gVertexBuffer->getDeviceAddress(); - geomDesc.content.triangles.vertexFormat = Format::R32G32B32_FLOAT; - geomDesc.content.triangles.vertexStride = sizeof(Vertex); - geomDesc.content.triangles.transform3x4 = gTransformBuffer->getDeviceAddress(); - accelerationStructureBuildInputs.geometryDescs = &geomDesc; - - // Query buffer size for acceleration structure build. - SLANG_RETURN_ON_FAIL(gDevice->getAccelerationStructurePrebuildInfo( - accelerationStructureBuildInputs, &accelerationStructurePrebuildInfo)); - // Allocate buffers for acceleration structure. - IBufferResource::Desc asDraftBufferDesc; - asDraftBufferDesc.type = IResource::Type::Buffer; - asDraftBufferDesc.defaultState = ResourceState::AccelerationStructure; - asDraftBufferDesc.sizeInBytes = (size_t)accelerationStructurePrebuildInfo.resultDataMaxSize; - ComPtr draftBuffer = gDevice->createBufferResource(asDraftBufferDesc); - IBufferResource::Desc scratchBufferDesc; - scratchBufferDesc.type = IResource::Type::Buffer; - scratchBufferDesc.defaultState = ResourceState::UnorderedAccess; - scratchBufferDesc.sizeInBytes = (size_t)accelerationStructurePrebuildInfo.scratchDataSize; - ComPtr scratchBuffer = gDevice->createBufferResource(scratchBufferDesc); - - // Build acceleration structure. - ComPtr compactedSizeQuery; - IQueryPool::Desc queryPoolDesc; - queryPoolDesc.count = 1; - queryPoolDesc.type = QueryType::AccelerationStructureCompactedSize; - SLANG_RETURN_ON_FAIL( - gDevice->createQueryPool(queryPoolDesc, compactedSizeQuery.writeRef())); - - ComPtr draftAS; - IAccelerationStructure::CreateDesc draftCreateDesc; - draftCreateDesc.buffer = draftBuffer; - draftCreateDesc.kind = IAccelerationStructure::Kind::BottomLevel; - draftCreateDesc.offset = 0; - draftCreateDesc.size = accelerationStructurePrebuildInfo.resultDataMaxSize; - SLANG_RETURN_ON_FAIL( - gDevice->createAccelerationStructure(draftCreateDesc, draftAS.writeRef())); - - compactedSizeQuery->reset(); - - auto commandBuffer = gTransientHeaps[0]->createCommandBuffer(); - auto encoder = commandBuffer->encodeRayTracingCommands(); - IAccelerationStructure::BuildDesc buildDesc = {}; - buildDesc.dest = draftAS; - buildDesc.inputs = accelerationStructureBuildInputs; - buildDesc.scratchData = scratchBuffer->getDeviceAddress(); - AccelerationStructureQueryDesc compactedSizeQueryDesc = {}; - compactedSizeQueryDesc.queryPool = compactedSizeQuery; - compactedSizeQueryDesc.queryType = QueryType::AccelerationStructureCompactedSize; - encoder->buildAccelerationStructure(buildDesc, 1, &compactedSizeQueryDesc); - encoder->endEncoding(); - commandBuffer->close(); - gQueue->executeCommandBuffer(commandBuffer); - gQueue->waitOnHost(); - - uint64_t compactedSize = 0; - compactedSizeQuery->getResult(0, 1, &compactedSize); - IBufferResource::Desc asBufferDesc; - asBufferDesc.type = IResource::Type::Buffer; - asBufferDesc.defaultState = ResourceState::AccelerationStructure; - asBufferDesc.sizeInBytes = (size_t)compactedSize; - gBLASBuffer = gDevice->createBufferResource(asBufferDesc); - IAccelerationStructure::CreateDesc createDesc; - createDesc.buffer = gBLASBuffer; - createDesc.kind = IAccelerationStructure::Kind::BottomLevel; - createDesc.offset = 0; - createDesc.size = (size_t)compactedSize; - gDevice->createAccelerationStructure(createDesc, gBLAS.writeRef()); - - commandBuffer = gTransientHeaps[0]->createCommandBuffer(); - encoder = commandBuffer->encodeRayTracingCommands(); - encoder->copyAccelerationStructure(gBLAS, draftAS, AccelerationStructureCopyMode::Compact); - encoder->endEncoding(); - commandBuffer->close(); - gQueue->executeCommandBuffer(commandBuffer); - gQueue->waitOnHost(); - } + initializeBase("Ray Tracing Pipeline", 1024, 768); + if (!isTestMode()) + { + gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) + { onMouseMove(e); }; + gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { onMouseUp(e); }; + gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) + { onMouseDown(e); }; + gWindow->events.keyDown = [this](const platform::KeyEventArgs& e) { onKeyDown(e); }; + gWindow->events.keyUp = [this](const platform::KeyEventArgs& e) { onKeyUp(e); }; + } + + IBufferResource::Desc vertexBufferDesc; + vertexBufferDesc.type = IResource::Type::Buffer; + vertexBufferDesc.sizeInBytes = kVertexCount * sizeof(Vertex); + vertexBufferDesc.defaultState = ResourceState::ShaderResource; + gVertexBuffer = gDevice->createBufferResource(vertexBufferDesc, &kVertexData[0]); + if (!gVertexBuffer) + return SLANG_FAIL; - // Build top level acceleration structure. - { - List instanceDescs; - instanceDescs.setCount(1); - instanceDescs[0].accelerationStructure = gBLAS->getDeviceAddress(); - instanceDescs[0].flags = - IAccelerationStructure::GeometryInstanceFlags::TriangleFacingCullDisable; - instanceDescs[0].instanceContributionToHitGroupIndex = 0; - instanceDescs[0].instanceID = 0; - instanceDescs[0].instanceMask = 0xFF; - float transformMatrix[] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}; - memcpy(&instanceDescs[0].transform[0][0], transformMatrix, sizeof(float) * 12); - - IBufferResource::Desc instanceBufferDesc; - instanceBufferDesc.type = IResource::Type::Buffer; - instanceBufferDesc.sizeInBytes = - instanceDescs.getCount() * sizeof(IAccelerationStructure::InstanceDesc); - instanceBufferDesc.defaultState = ResourceState::ShaderResource; - gInstanceBuffer = gDevice->createBufferResource(instanceBufferDesc, instanceDescs.getBuffer()); - if (!gInstanceBuffer) + IBufferResource::Desc indexBufferDesc; + indexBufferDesc.type = IResource::Type::Buffer; + indexBufferDesc.sizeInBytes = kIndexCount * sizeof(int32_t); + indexBufferDesc.defaultState = ResourceState::ShaderResource; + gIndexBuffer = gDevice->createBufferResource(indexBufferDesc, &kIndexData[0]); + if (!gIndexBuffer) return SLANG_FAIL; - IAccelerationStructure::BuildInputs accelerationStructureBuildInputs = {}; - IAccelerationStructure::PrebuildInfo accelerationStructurePrebuildInfo = {}; - accelerationStructureBuildInputs.descCount = 1; - accelerationStructureBuildInputs.kind = IAccelerationStructure::Kind::TopLevel; - accelerationStructureBuildInputs.instanceDescs = gInstanceBuffer->getDeviceAddress(); - - // Query buffer size for acceleration structure build. - SLANG_RETURN_ON_FAIL(gDevice->getAccelerationStructurePrebuildInfo( - accelerationStructureBuildInputs, &accelerationStructurePrebuildInfo)); - - IBufferResource::Desc asBufferDesc; - asBufferDesc.type = IResource::Type::Buffer; - asBufferDesc.defaultState = ResourceState::AccelerationStructure; - asBufferDesc.sizeInBytes = (size_t)accelerationStructurePrebuildInfo.resultDataMaxSize; - gTLASBuffer = gDevice->createBufferResource(asBufferDesc); - - IBufferResource::Desc scratchBufferDesc; - scratchBufferDesc.type = IResource::Type::Buffer; - scratchBufferDesc.defaultState = ResourceState::UnorderedAccess; - scratchBufferDesc.sizeInBytes = (size_t)accelerationStructurePrebuildInfo.scratchDataSize; - ComPtr scratchBuffer = gDevice->createBufferResource(scratchBufferDesc); - - IAccelerationStructure::CreateDesc createDesc; - createDesc.buffer = gTLASBuffer; - createDesc.kind = IAccelerationStructure::Kind::TopLevel; - createDesc.offset = 0; - createDesc.size = (size_t)accelerationStructurePrebuildInfo.resultDataMaxSize; - SLANG_RETURN_ON_FAIL(gDevice->createAccelerationStructure(createDesc, gTLAS.writeRef())); - - auto commandBuffer = gTransientHeaps[0]->createCommandBuffer(); - auto encoder = commandBuffer->encodeRayTracingCommands(); - IAccelerationStructure::BuildDesc buildDesc = {}; - buildDesc.dest = gTLAS; - buildDesc.inputs = accelerationStructureBuildInputs; - buildDesc.scratchData = scratchBuffer->getDeviceAddress(); - encoder->buildAccelerationStructure(buildDesc, 0, nullptr); - encoder->endEncoding(); - commandBuffer->close(); - gQueue->executeCommandBuffer(commandBuffer); - gQueue->waitOnHost(); - } + IBufferResource::Desc primitiveBufferDesc; + primitiveBufferDesc.type = IResource::Type::Buffer; + primitiveBufferDesc.sizeInBytes = kPrimitiveCount * sizeof(Primitive); + primitiveBufferDesc.elementSize = sizeof(Primitive); + primitiveBufferDesc.defaultState = ResourceState::ShaderResource; + gPrimitiveBuffer = gDevice->createBufferResource(primitiveBufferDesc, &kPrimitiveData[0]); + if (!gPrimitiveBuffer) + return SLANG_FAIL; - IBufferResource::Desc fullScreenVertexBufferDesc; - fullScreenVertexBufferDesc.type = IResource::Type::Buffer; - fullScreenVertexBufferDesc.sizeInBytes = - FullScreenTriangle::kVertexCount * sizeof(FullScreenTriangle::Vertex); - fullScreenVertexBufferDesc.defaultState = ResourceState::VertexBuffer; - gFullScreenVertexBuffer = gDevice->createBufferResource( - fullScreenVertexBufferDesc, &FullScreenTriangle::kVertices[0]); - if (!gFullScreenVertexBuffer) - return SLANG_FAIL; - - InputElementDesc inputElements[] = { - {"POSITION", 0, Format::R32G32_FLOAT, offsetof(FullScreenTriangle::Vertex, position)}, - }; - auto inputLayout = gDevice->createInputLayout(sizeof(FullScreenTriangle::Vertex), &inputElements[0], SLANG_COUNT_OF(inputElements)); - if (!inputLayout) - return SLANG_FAIL; - - ComPtr shaderProgram; - SLANG_RETURN_ON_FAIL(loadShaderProgram(gDevice, false, shaderProgram.writeRef())); - GraphicsPipelineStateDesc desc; - desc.inputLayout = inputLayout; - desc.program = shaderProgram; - desc.framebufferLayout = gFramebufferLayout; - gPresentPipelineState = gDevice->createGraphicsPipelineState(desc); - if (!gPresentPipelineState) - return SLANG_FAIL; - - const char* hitgroupNames[] = {"hitgroup0", "hitgroup1"}; - - ComPtr rayTracingProgram; - SLANG_RETURN_ON_FAIL( - loadShaderProgram(gDevice, true, rayTracingProgram.writeRef())); - RayTracingPipelineStateDesc rtpDesc = {}; - rtpDesc.program = rayTracingProgram; - rtpDesc.hitGroupCount = 2; - HitGroupDesc hitGroups[2]; - hitGroups[0].closestHitEntryPoint = "closestHitShader"; - hitGroups[0].hitGroupName = hitgroupNames[0]; - hitGroups[1].closestHitEntryPoint = "shadowRayHitShader"; - hitGroups[1].hitGroupName = hitgroupNames[1]; - rtpDesc.hitGroups = hitGroups; - rtpDesc.maxRayPayloadSize = 64; - rtpDesc.maxRecursion = 2; - SLANG_RETURN_ON_FAIL( - gDevice->createRayTracingPipelineState(rtpDesc, gRenderPipelineState.writeRef())); - if (!gRenderPipelineState) - return SLANG_FAIL; - - IShaderTable::Desc shaderTableDesc = {}; - const char* raygenName = "rayGenShader"; - const char* missName = "missShader"; - shaderTableDesc.program = rayTracingProgram; - shaderTableDesc.hitGroupCount = 2; - shaderTableDesc.hitGroupNames = hitgroupNames; - shaderTableDesc.rayGenShaderCount = 1; - shaderTableDesc.rayGenShaderEntryPointNames = &raygenName; - shaderTableDesc.missShaderCount = 1; - shaderTableDesc.missShaderEntryPointNames = &missName; - SLANG_RETURN_ON_FAIL(gDevice->createShaderTable(shaderTableDesc, gShaderTable.writeRef())); - - createResultTexture(); - return SLANG_OK; -} - -void createResultTexture() -{ - ITextureResource::Desc resultTextureDesc = {}; - resultTextureDesc.type = IResource::Type::Texture2D; - resultTextureDesc.numMipLevels = 1; - resultTextureDesc.size.width = windowWidth; - resultTextureDesc.size.height = windowHeight; - resultTextureDesc.size.depth = 1; - resultTextureDesc.defaultState = ResourceState::UnorderedAccess; - resultTextureDesc.format = Format::R16G16B16A16_FLOAT; - gResultTexture = gDevice->createTextureResource(resultTextureDesc); - IResourceView::Desc resultUAVDesc = {}; - resultUAVDesc.format = resultTextureDesc.format; - resultUAVDesc.type = IResourceView::Type::UnorderedAccess; - gResultTextureUAV = gDevice->createTextureView(gResultTexture, resultUAVDesc); -} - -virtual void windowSizeChanged() override -{ - WindowedAppBase::windowSizeChanged(); - createResultTexture(); -} + IResourceView::Desc primitiveSRVDesc = {}; + primitiveSRVDesc.format = Format::Unknown; + primitiveSRVDesc.type = IResourceView::Type::ShaderResource; + gPrimitiveBufferSRV = + gDevice->createBufferView(gPrimitiveBuffer, nullptr, primitiveSRVDesc); + + IBufferResource::Desc transformBufferDesc; + transformBufferDesc.type = IResource::Type::Buffer; + transformBufferDesc.sizeInBytes = sizeof(float) * 12; + transformBufferDesc.defaultState = ResourceState::ShaderResource; + float transformData[12] = + {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}; + gTransformBuffer = gDevice->createBufferResource(transformBufferDesc, &transformData); + if (!gTransformBuffer) + return SLANG_FAIL; + // Build bottom level acceleration structure. + { + IAccelerationStructure::BuildInputs accelerationStructureBuildInputs; + IAccelerationStructure::PrebuildInfo accelerationStructurePrebuildInfo; + accelerationStructureBuildInputs.descCount = 1; + accelerationStructureBuildInputs.kind = IAccelerationStructure::Kind::BottomLevel; + accelerationStructureBuildInputs.flags = + IAccelerationStructure::BuildFlags::AllowCompaction; + IAccelerationStructure::GeometryDesc geomDesc; + geomDesc.flags = IAccelerationStructure::GeometryFlags::Opaque; + geomDesc.type = IAccelerationStructure::GeometryType::Triangles; + geomDesc.content.triangles.indexCount = kIndexCount; + geomDesc.content.triangles.indexData = gIndexBuffer->getDeviceAddress(); + geomDesc.content.triangles.indexFormat = Format::R32_UINT; + geomDesc.content.triangles.vertexCount = kVertexCount; + geomDesc.content.triangles.vertexData = gVertexBuffer->getDeviceAddress(); + geomDesc.content.triangles.vertexFormat = Format::R32G32B32_FLOAT; + geomDesc.content.triangles.vertexStride = sizeof(Vertex); + geomDesc.content.triangles.transform3x4 = gTransformBuffer->getDeviceAddress(); + accelerationStructureBuildInputs.geometryDescs = &geomDesc; + + // Query buffer size for acceleration structure build. + SLANG_RETURN_ON_FAIL(gDevice->getAccelerationStructurePrebuildInfo( + accelerationStructureBuildInputs, + &accelerationStructurePrebuildInfo)); + // Allocate buffers for acceleration structure. + IBufferResource::Desc asDraftBufferDesc; + asDraftBufferDesc.type = IResource::Type::Buffer; + asDraftBufferDesc.defaultState = ResourceState::AccelerationStructure; + asDraftBufferDesc.sizeInBytes = + (size_t)accelerationStructurePrebuildInfo.resultDataMaxSize; + ComPtr draftBuffer = gDevice->createBufferResource(asDraftBufferDesc); + IBufferResource::Desc scratchBufferDesc; + scratchBufferDesc.type = IResource::Type::Buffer; + scratchBufferDesc.defaultState = ResourceState::UnorderedAccess; + scratchBufferDesc.sizeInBytes = + (size_t)accelerationStructurePrebuildInfo.scratchDataSize; + ComPtr scratchBuffer = + gDevice->createBufferResource(scratchBufferDesc); + + // Build acceleration structure. + ComPtr compactedSizeQuery; + IQueryPool::Desc queryPoolDesc; + queryPoolDesc.count = 1; + queryPoolDesc.type = QueryType::AccelerationStructureCompactedSize; + SLANG_RETURN_ON_FAIL( + gDevice->createQueryPool(queryPoolDesc, compactedSizeQuery.writeRef())); + + ComPtr draftAS; + IAccelerationStructure::CreateDesc draftCreateDesc; + draftCreateDesc.buffer = draftBuffer; + draftCreateDesc.kind = IAccelerationStructure::Kind::BottomLevel; + draftCreateDesc.offset = 0; + draftCreateDesc.size = accelerationStructurePrebuildInfo.resultDataMaxSize; + SLANG_RETURN_ON_FAIL( + gDevice->createAccelerationStructure(draftCreateDesc, draftAS.writeRef())); + + compactedSizeQuery->reset(); + + auto commandBuffer = gTransientHeaps[0]->createCommandBuffer(); + auto encoder = commandBuffer->encodeRayTracingCommands(); + IAccelerationStructure::BuildDesc buildDesc = {}; + buildDesc.dest = draftAS; + buildDesc.inputs = accelerationStructureBuildInputs; + buildDesc.scratchData = scratchBuffer->getDeviceAddress(); + AccelerationStructureQueryDesc compactedSizeQueryDesc = {}; + compactedSizeQueryDesc.queryPool = compactedSizeQuery; + compactedSizeQueryDesc.queryType = QueryType::AccelerationStructureCompactedSize; + encoder->buildAccelerationStructure(buildDesc, 1, &compactedSizeQueryDesc); + encoder->endEncoding(); + commandBuffer->close(); + gQueue->executeCommandBuffer(commandBuffer); + gQueue->waitOnHost(); + + uint64_t compactedSize = 0; + compactedSizeQuery->getResult(0, 1, &compactedSize); + IBufferResource::Desc asBufferDesc; + asBufferDesc.type = IResource::Type::Buffer; + asBufferDesc.defaultState = ResourceState::AccelerationStructure; + asBufferDesc.sizeInBytes = (size_t)compactedSize; + gBLASBuffer = gDevice->createBufferResource(asBufferDesc); + IAccelerationStructure::CreateDesc createDesc; + createDesc.buffer = gBLASBuffer; + createDesc.kind = IAccelerationStructure::Kind::BottomLevel; + createDesc.offset = 0; + createDesc.size = (size_t)compactedSize; + gDevice->createAccelerationStructure(createDesc, gBLAS.writeRef()); + + commandBuffer = gTransientHeaps[0]->createCommandBuffer(); + encoder = commandBuffer->encodeRayTracingCommands(); + encoder->copyAccelerationStructure( + gBLAS, + draftAS, + AccelerationStructureCopyMode::Compact); + encoder->endEncoding(); + commandBuffer->close(); + gQueue->executeCommandBuffer(commandBuffer); + gQueue->waitOnHost(); + } + + // Build top level acceleration structure. + { + List instanceDescs; + instanceDescs.setCount(1); + instanceDescs[0].accelerationStructure = gBLAS->getDeviceAddress(); + instanceDescs[0].flags = + IAccelerationStructure::GeometryInstanceFlags::TriangleFacingCullDisable; + instanceDescs[0].instanceContributionToHitGroupIndex = 0; + instanceDescs[0].instanceID = 0; + instanceDescs[0].instanceMask = 0xFF; + float transformMatrix[] = + {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}; + memcpy(&instanceDescs[0].transform[0][0], transformMatrix, sizeof(float) * 12); + + IBufferResource::Desc instanceBufferDesc; + instanceBufferDesc.type = IResource::Type::Buffer; + instanceBufferDesc.sizeInBytes = + instanceDescs.getCount() * sizeof(IAccelerationStructure::InstanceDesc); + instanceBufferDesc.defaultState = ResourceState::ShaderResource; + gInstanceBuffer = + gDevice->createBufferResource(instanceBufferDesc, instanceDescs.getBuffer()); + if (!gInstanceBuffer) + return SLANG_FAIL; + + IAccelerationStructure::BuildInputs accelerationStructureBuildInputs = {}; + IAccelerationStructure::PrebuildInfo accelerationStructurePrebuildInfo = {}; + accelerationStructureBuildInputs.descCount = 1; + accelerationStructureBuildInputs.kind = IAccelerationStructure::Kind::TopLevel; + accelerationStructureBuildInputs.instanceDescs = gInstanceBuffer->getDeviceAddress(); + + // Query buffer size for acceleration structure build. + SLANG_RETURN_ON_FAIL(gDevice->getAccelerationStructurePrebuildInfo( + accelerationStructureBuildInputs, + &accelerationStructurePrebuildInfo)); + + IBufferResource::Desc asBufferDesc; + asBufferDesc.type = IResource::Type::Buffer; + asBufferDesc.defaultState = ResourceState::AccelerationStructure; + asBufferDesc.sizeInBytes = (size_t)accelerationStructurePrebuildInfo.resultDataMaxSize; + gTLASBuffer = gDevice->createBufferResource(asBufferDesc); + + IBufferResource::Desc scratchBufferDesc; + scratchBufferDesc.type = IResource::Type::Buffer; + scratchBufferDesc.defaultState = ResourceState::UnorderedAccess; + scratchBufferDesc.sizeInBytes = + (size_t)accelerationStructurePrebuildInfo.scratchDataSize; + ComPtr scratchBuffer = + gDevice->createBufferResource(scratchBufferDesc); + + IAccelerationStructure::CreateDesc createDesc; + createDesc.buffer = gTLASBuffer; + createDesc.kind = IAccelerationStructure::Kind::TopLevel; + createDesc.offset = 0; + createDesc.size = (size_t)accelerationStructurePrebuildInfo.resultDataMaxSize; + SLANG_RETURN_ON_FAIL( + gDevice->createAccelerationStructure(createDesc, gTLAS.writeRef())); + + auto commandBuffer = gTransientHeaps[0]->createCommandBuffer(); + auto encoder = commandBuffer->encodeRayTracingCommands(); + IAccelerationStructure::BuildDesc buildDesc = {}; + buildDesc.dest = gTLAS; + buildDesc.inputs = accelerationStructureBuildInputs; + buildDesc.scratchData = scratchBuffer->getDeviceAddress(); + encoder->buildAccelerationStructure(buildDesc, 0, nullptr); + encoder->endEncoding(); + commandBuffer->close(); + gQueue->executeCommandBuffer(commandBuffer); + gQueue->waitOnHost(); + } + + IBufferResource::Desc fullScreenVertexBufferDesc; + fullScreenVertexBufferDesc.type = IResource::Type::Buffer; + fullScreenVertexBufferDesc.sizeInBytes = + FullScreenTriangle::kVertexCount * sizeof(FullScreenTriangle::Vertex); + fullScreenVertexBufferDesc.defaultState = ResourceState::VertexBuffer; + gFullScreenVertexBuffer = gDevice->createBufferResource( + fullScreenVertexBufferDesc, + &FullScreenTriangle::kVertices[0]); + if (!gFullScreenVertexBuffer) + return SLANG_FAIL; -glm::vec3 getVectorFromSphericalAngles(float theta, float phi) -{ - auto sinTheta = sin(theta); - auto cosTheta = cos(theta); - auto sinPhi = sin(phi); - auto cosPhi = cos(phi); - return glm::vec3(-sinTheta * cosPhi, sinPhi, -cosTheta * cosPhi); -} -void updateUniforms() -{ - gUniforms.screenWidth = (float)windowWidth; - gUniforms.screenHeight = (float)windowHeight; - if (!lastTime) - lastTime = getCurrentTime(); - uint64_t currentTime = getCurrentTime(); - float deltaTime = float(double(currentTime - lastTime) / double(getTimerFrequency())); - lastTime = currentTime; - - auto camDir = - getVectorFromSphericalAngles(cameraOrientationAngles[0], cameraOrientationAngles[1]); - auto camUp = getVectorFromSphericalAngles( - cameraOrientationAngles[0], cameraOrientationAngles[1] + glm::pi() * 0.5f); - auto camRight = glm::cross(camDir, camUp); - - glm::vec3 movement = glm::vec3(0); - if (wPressed) - movement += camDir; - if (sPressed) - movement -= camDir; - if (aPressed) - movement -= camRight; - if (dPressed) - movement += camRight; - - cameraPosition += deltaTime * translationScale * movement; - - memcpy(gUniforms.cameraDir, &camDir, sizeof(float) * 3); - memcpy(gUniforms.cameraUp, &camUp, sizeof(float) * 3); - memcpy(gUniforms.cameraRight, &camRight, sizeof(float) * 3); - memcpy(gUniforms.cameraPosition, &cameraPosition, sizeof(float) * 3); - auto lightDir = glm::normalize(glm::vec3(1.0f, 3.0f, 2.0f)); - memcpy(gUniforms.lightDir, &lightDir, sizeof(float) * 3); -} - -virtual void renderFrame(int frameBufferIndex) override -{ - updateUniforms(); + InputElementDesc inputElements[] = { + {"POSITION", 0, Format::R32G32_FLOAT, offsetof(FullScreenTriangle::Vertex, position)}, + }; + auto inputLayout = gDevice->createInputLayout( + sizeof(FullScreenTriangle::Vertex), + &inputElements[0], + SLANG_COUNT_OF(inputElements)); + if (!inputLayout) + return SLANG_FAIL; + + ComPtr shaderProgram; + SLANG_RETURN_ON_FAIL(loadShaderProgram(gDevice, false, shaderProgram.writeRef())); + GraphicsPipelineStateDesc desc; + desc.inputLayout = inputLayout; + desc.program = shaderProgram; + desc.framebufferLayout = gFramebufferLayout; + gPresentPipelineState = gDevice->createGraphicsPipelineState(desc); + if (!gPresentPipelineState) + return SLANG_FAIL; + + const char* hitgroupNames[] = {"hitgroup0", "hitgroup1"}; + + ComPtr rayTracingProgram; + SLANG_RETURN_ON_FAIL(loadShaderProgram(gDevice, true, rayTracingProgram.writeRef())); + RayTracingPipelineStateDesc rtpDesc = {}; + rtpDesc.program = rayTracingProgram; + rtpDesc.hitGroupCount = 2; + HitGroupDesc hitGroups[2]; + hitGroups[0].closestHitEntryPoint = "closestHitShader"; + hitGroups[0].hitGroupName = hitgroupNames[0]; + hitGroups[1].closestHitEntryPoint = "shadowRayHitShader"; + hitGroups[1].hitGroupName = hitgroupNames[1]; + rtpDesc.hitGroups = hitGroups; + rtpDesc.maxRayPayloadSize = 64; + rtpDesc.maxRecursion = 2; + SLANG_RETURN_ON_FAIL( + gDevice->createRayTracingPipelineState(rtpDesc, gRenderPipelineState.writeRef())); + if (!gRenderPipelineState) + return SLANG_FAIL; + + IShaderTable::Desc shaderTableDesc = {}; + const char* raygenName = "rayGenShader"; + const char* missName = "missShader"; + shaderTableDesc.program = rayTracingProgram; + shaderTableDesc.hitGroupCount = 2; + shaderTableDesc.hitGroupNames = hitgroupNames; + shaderTableDesc.rayGenShaderCount = 1; + shaderTableDesc.rayGenShaderEntryPointNames = &raygenName; + shaderTableDesc.missShaderCount = 1; + shaderTableDesc.missShaderEntryPointNames = &missName; + SLANG_RETURN_ON_FAIL(gDevice->createShaderTable(shaderTableDesc, gShaderTable.writeRef())); + + createResultTexture(); + return SLANG_OK; + } + + void createResultTexture() { - ComPtr renderCommandBuffer = - gTransientHeaps[frameBufferIndex]->createCommandBuffer(); - auto renderEncoder = renderCommandBuffer->encodeRayTracingCommands(); - IShaderObject* rootObject = nullptr; - renderEncoder->bindPipeline(gRenderPipelineState, &rootObject); - auto cursor = ShaderCursor(rootObject); - cursor["resultTexture"].setResource(gResultTextureUAV); - cursor["uniforms"].setData(&gUniforms, sizeof(Uniforms)); - cursor["sceneBVH"].setResource(gTLAS); - cursor["primitiveBuffer"].setResource(gPrimitiveBufferSRV); - renderEncoder->dispatchRays(0, gShaderTable, windowWidth, windowHeight, 1); - renderEncoder->endEncoding(); - renderCommandBuffer->close(); - gQueue->executeCommandBuffer(renderCommandBuffer); + ITextureResource::Desc resultTextureDesc = {}; + resultTextureDesc.type = IResource::Type::Texture2D; + resultTextureDesc.numMipLevels = 1; + resultTextureDesc.size.width = windowWidth; + resultTextureDesc.size.height = windowHeight; + resultTextureDesc.size.depth = 1; + resultTextureDesc.defaultState = ResourceState::UnorderedAccess; + resultTextureDesc.format = Format::R16G16B16A16_FLOAT; + gResultTexture = gDevice->createTextureResource(resultTextureDesc); + IResourceView::Desc resultUAVDesc = {}; + resultUAVDesc.format = resultTextureDesc.format; + resultUAVDesc.type = IResourceView::Type::UnorderedAccess; + gResultTextureUAV = gDevice->createTextureView(gResultTexture, resultUAVDesc); } + virtual void windowSizeChanged() override { - ComPtr presentCommandBuffer = - gTransientHeaps[frameBufferIndex]->createCommandBuffer(); - auto presentEncoder = presentCommandBuffer->encodeRenderCommands( - gRenderPass, gFramebuffers[frameBufferIndex]); - gfx::Viewport viewport = {}; - viewport.maxZ = 1.0f; - viewport.extentX = (float)windowWidth; - viewport.extentY = (float)windowHeight; - presentEncoder->setViewportAndScissor(viewport); - auto rootObject = presentEncoder->bindPipeline(gPresentPipelineState); - auto cursor = ShaderCursor(rootObject->getEntryPoint(1)); - cursor["t"].setResource(gResultTextureUAV); - presentEncoder->setVertexBuffer( - 0, gFullScreenVertexBuffer); - presentEncoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); - presentEncoder->draw(3); - presentEncoder->endEncoding(); - presentCommandBuffer->close(); - gQueue->executeCommandBuffer(presentCommandBuffer); + WindowedAppBase::windowSizeChanged(); + createResultTexture(); } - if (!isTestMode()) + glm::vec3 getVectorFromSphericalAngles(float theta, float phi) { - // With that, we are done drawing for one frame, and ready for the next. - // - gSwapchain->present(); + auto sinTheta = sin(theta); + auto cosTheta = cos(theta); + auto sinPhi = sin(phi); + auto cosPhi = cos(phi); + return glm::vec3(-sinTheta * cosPhi, sinPhi, -cosTheta * cosPhi); + } + void updateUniforms() + { + gUniforms.screenWidth = (float)windowWidth; + gUniforms.screenHeight = (float)windowHeight; + if (!lastTime) + lastTime = getCurrentTime(); + uint64_t currentTime = getCurrentTime(); + float deltaTime = float(double(currentTime - lastTime) / double(getTimerFrequency())); + lastTime = currentTime; + + auto camDir = + getVectorFromSphericalAngles(cameraOrientationAngles[0], cameraOrientationAngles[1]); + auto camUp = getVectorFromSphericalAngles( + cameraOrientationAngles[0], + cameraOrientationAngles[1] + glm::pi() * 0.5f); + auto camRight = glm::cross(camDir, camUp); + + glm::vec3 movement = glm::vec3(0); + if (wPressed) + movement += camDir; + if (sPressed) + movement -= camDir; + if (aPressed) + movement -= camRight; + if (dPressed) + movement += camRight; + + cameraPosition += deltaTime * translationScale * movement; + + memcpy(gUniforms.cameraDir, &camDir, sizeof(float) * 3); + memcpy(gUniforms.cameraUp, &camUp, sizeof(float) * 3); + memcpy(gUniforms.cameraRight, &camRight, sizeof(float) * 3); + memcpy(gUniforms.cameraPosition, &cameraPosition, sizeof(float) * 3); + auto lightDir = glm::normalize(glm::vec3(1.0f, 3.0f, 2.0f)); + memcpy(gUniforms.lightDir, &lightDir, sizeof(float) * 3); } -} + virtual void renderFrame(int frameBufferIndex) override + { + updateUniforms(); + { + ComPtr renderCommandBuffer = + gTransientHeaps[frameBufferIndex]->createCommandBuffer(); + auto renderEncoder = renderCommandBuffer->encodeRayTracingCommands(); + IShaderObject* rootObject = nullptr; + renderEncoder->bindPipeline(gRenderPipelineState, &rootObject); + auto cursor = ShaderCursor(rootObject); + cursor["resultTexture"].setResource(gResultTextureUAV); + cursor["uniforms"].setData(&gUniforms, sizeof(Uniforms)); + cursor["sceneBVH"].setResource(gTLAS); + cursor["primitiveBuffer"].setResource(gPrimitiveBufferSRV); + renderEncoder->dispatchRays(0, gShaderTable, windowWidth, windowHeight, 1); + renderEncoder->endEncoding(); + renderCommandBuffer->close(); + gQueue->executeCommandBuffer(renderCommandBuffer); + } + + { + ComPtr presentCommandBuffer = + gTransientHeaps[frameBufferIndex]->createCommandBuffer(); + auto presentEncoder = presentCommandBuffer->encodeRenderCommands( + gRenderPass, + gFramebuffers[frameBufferIndex]); + gfx::Viewport viewport = {}; + viewport.maxZ = 1.0f; + viewport.extentX = (float)windowWidth; + viewport.extentY = (float)windowHeight; + presentEncoder->setViewportAndScissor(viewport); + auto rootObject = presentEncoder->bindPipeline(gPresentPipelineState); + auto cursor = ShaderCursor(rootObject->getEntryPoint(1)); + cursor["t"].setResource(gResultTextureUAV); + presentEncoder->setVertexBuffer(0, gFullScreenVertexBuffer); + presentEncoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); + presentEncoder->draw(3); + presentEncoder->endEncoding(); + presentCommandBuffer->close(); + gQueue->executeCommandBuffer(presentCommandBuffer); + } + + if (!isTestMode()) + { + // With that, we are done drawing for one frame, and ready for the next. + // + gSwapchain->present(); + } + } }; // This macro instantiates an appropriate main function to diff --git a/examples/ray-tracing/main.cpp b/examples/ray-tracing/main.cpp index 4ec5070d8..22111149c 100644 --- a/examples/ray-tracing/main.cpp +++ b/examples/ray-tracing/main.cpp @@ -3,14 +3,14 @@ // This file implements an example of hardware ray-tracing using // Slang shaders and the `gfx` graphics API. -#include "slang.h" -#include "slang-gfx.h" +#include "examples/example-base/example-base.h" #include "gfx-util/shader-cursor.h" -#include "tools/platform/window.h" -#include "tools/platform/vector-math.h" #include "slang-com-ptr.h" +#include "slang-gfx.h" +#include "slang.h" #include "source/core/slang-basic.h" -#include "examples/example-base/example-base.h" +#include "tools/platform/vector-math.h" +#include "tools/platform/window.h" using namespace gfx; using namespace Slang; @@ -36,8 +36,7 @@ struct Vertex // Define geometry data for our test scene. // The scene contains a floor plane, and a cube placed on top of it at the center. static const int kVertexCount = 24; -static const Vertex kVertexData[kVertexCount] = -{ +static const Vertex kVertexData[kVertexCount] = { // Floor plane {{-100.0f, 0, 100.0f}}, {{100.0f, 0, 100.0f}}, @@ -70,15 +69,9 @@ static const Vertex kVertexData[kVertexCount] = {{1.0f, 0.0, -1.0f}}, }; static const int kIndexCount = 36; -static const int kIndexData[kIndexCount] = -{ - 0, 1, 2, 0, 2, 3, - 4, 5, 6, 4, 6, 7, - 8, 9, 10, 8, 10, 11, - 12, 13, 14, 12, 14, 15, - 16, 17, 18, 16, 18, 19, - 20, 21, 22, 20, 22, 23 -}; +static const int kIndexData[kIndexCount] = {0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, + 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, + 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23}; struct Primitive { @@ -86,8 +79,7 @@ struct Primitive float color[4]; }; static const int kPrimitiveCount = 12; -static const Primitive kPrimitiveData[kPrimitiveCount] = -{ +static const Primitive kPrimitiveData[kPrimitiveCount] = { {{0.0f, 1.0f, 0.0f, 0.0f}, {0.75f, 0.8f, 0.85f, 1.0f}}, {{0.0f, 1.0f, 0.0f, 0.0f}, {0.75f, 0.8f, 0.85f, 1.0f}}, {{0.0f, 1.0f, 0.0f, 0.0f}, {0.95f, 0.85f, 0.05f, 1.0f}}, @@ -134,525 +126,539 @@ struct RayTracing : public WindowedAppBase { -Uniforms gUniforms = {}; + Uniforms gUniforms = {}; -// Many Slang API functions return detailed diagnostic information -// (error messages, warnings, etc.) as a "blob" of data, or return -// a null blob pointer instead if there were no issues. -// -// For convenience, we define a subroutine that will dump the information -// in a diagnostic blob if one is produced, and skip it otherwise. -// -void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob) -{ - if( diagnosticsBlob != nullptr ) + // Many Slang API functions return detailed diagnostic information + // (error messages, warnings, etc.) as a "blob" of data, or return + // a null blob pointer instead if there were no issues. + // + // For convenience, we define a subroutine that will dump the information + // in a diagnostic blob if one is produced, and skip it otherwise. + // + void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob) { - printf("%s", (const char*) diagnosticsBlob->getBufferPointer()); + if (diagnosticsBlob != nullptr) + { + printf("%s", (const char*)diagnosticsBlob->getBufferPointer()); #ifdef _WIN32 - _Win32OutputDebugString((const char*)diagnosticsBlob->getBufferPointer()); + _Win32OutputDebugString((const char*)diagnosticsBlob->getBufferPointer()); #endif + } } -} -// Load and compile shader code from souce. -gfx::Result loadShaderProgram( - gfx::IDevice* device, bool isComputePipeline, gfx::IShaderProgram** outProgram) -{ - ComPtr slangSession; - slangSession = device->getSlangSession(); - - ComPtr diagnosticsBlob; - Slang::String path = resourceBase.resolveResource("shaders.slang"); - slang::IModule* module = slangSession->loadModule(path.getBuffer(), diagnosticsBlob.writeRef()); - diagnoseIfNeeded(diagnosticsBlob); - if(!module) - return SLANG_FAIL; - - Slang::List componentTypes; - componentTypes.add(module); - if (isComputePipeline) + // Load and compile shader code from souce. + gfx::Result loadShaderProgram( + gfx::IDevice* device, + bool isComputePipeline, + gfx::IShaderProgram** outProgram) { - ComPtr computeEntryPoint; - SLANG_RETURN_ON_FAIL(module->findEntryPointByName("computeMain", computeEntryPoint.writeRef())); - componentTypes.add(computeEntryPoint); - } - else - { - ComPtr entryPoint; - SLANG_RETURN_ON_FAIL(module->findEntryPointByName("vertexMain", entryPoint.writeRef())); - componentTypes.add(entryPoint); - SLANG_RETURN_ON_FAIL(module->findEntryPointByName("fragmentMain", entryPoint.writeRef())); - componentTypes.add(entryPoint); - } - - ComPtr linkedProgram; - SlangResult result = slangSession->createCompositeComponentType( - componentTypes.getBuffer(), - componentTypes.getCount(), - linkedProgram.writeRef(), - diagnosticsBlob.writeRef()); - diagnoseIfNeeded(diagnosticsBlob); - SLANG_RETURN_ON_FAIL(result); + ComPtr slangSession; + slangSession = device->getSlangSession(); + + ComPtr diagnosticsBlob; + Slang::String path = resourceBase.resolveResource("shaders.slang"); + slang::IModule* module = + slangSession->loadModule(path.getBuffer(), diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + if (!module) + return SLANG_FAIL; - if (isTestMode()) - { - printEntrypointHashes(componentTypes.getCount() - 1, 1, linkedProgram); + Slang::List componentTypes; + componentTypes.add(module); + if (isComputePipeline) + { + ComPtr computeEntryPoint; + SLANG_RETURN_ON_FAIL( + module->findEntryPointByName("computeMain", computeEntryPoint.writeRef())); + componentTypes.add(computeEntryPoint); + } + else + { + ComPtr entryPoint; + SLANG_RETURN_ON_FAIL(module->findEntryPointByName("vertexMain", entryPoint.writeRef())); + componentTypes.add(entryPoint); + SLANG_RETURN_ON_FAIL( + module->findEntryPointByName("fragmentMain", entryPoint.writeRef())); + componentTypes.add(entryPoint); + } + + ComPtr linkedProgram; + SlangResult result = slangSession->createCompositeComponentType( + componentTypes.getBuffer(), + componentTypes.getCount(), + linkedProgram.writeRef(), + diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + SLANG_RETURN_ON_FAIL(result); + + if (isTestMode()) + { + printEntrypointHashes(componentTypes.getCount() - 1, 1, linkedProgram); + } + + gfx::IShaderProgram::Desc programDesc = {}; + programDesc.slangGlobalScope = linkedProgram; + SLANG_RETURN_ON_FAIL(device->createProgram(programDesc, outProgram)); + + return SLANG_OK; } - gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangGlobalScope = linkedProgram; - SLANG_RETURN_ON_FAIL(device->createProgram(programDesc, outProgram)); - - return SLANG_OK; -} - -ComPtr gPresentPipelineState; -ComPtr gRenderPipelineState; -ComPtr gFullScreenVertexBuffer; -ComPtr gVertexBuffer; -ComPtr gIndexBuffer; -ComPtr gPrimitiveBuffer; -ComPtr gTransformBuffer; -ComPtr gPrimitiveBufferSRV; -ComPtr gInstanceBuffer; -ComPtr gBLASBuffer; -ComPtr gBLAS; -ComPtr gTLASBuffer; -ComPtr gTLAS; -ComPtr gResultTexture; -ComPtr gResultTextureUAV; - -uint64_t lastTime = 0; - -// glm::vec3 lightDir = normalize(glm::vec3(10, 10, 10)); -// glm::vec3 lightColor = glm::vec3(1, 1, 1); - -glm::vec3 cameraPosition = glm::vec3(-2.53f, 2.72f, 4.3f); -float cameraOrientationAngles[2] = {-0.475f, -0.35f}; // Spherical angles (theta, phi). - -float translationScale = 0.5f; -float rotationScale = 0.01f; - -// In order to control camera movement, we will -// use good old WASD -bool wPressed = false; -bool aPressed = false; -bool sPressed = false; -bool dPressed = false; - -bool isMouseDown = false; -float lastMouseX = 0.0f; -float lastMouseY = 0.0f; - -void setKeyState(platform::KeyCode key, bool state) -{ - switch (key) + ComPtr gPresentPipelineState; + ComPtr gRenderPipelineState; + ComPtr gFullScreenVertexBuffer; + ComPtr gVertexBuffer; + ComPtr gIndexBuffer; + ComPtr gPrimitiveBuffer; + ComPtr gTransformBuffer; + ComPtr gPrimitiveBufferSRV; + ComPtr gInstanceBuffer; + ComPtr gBLASBuffer; + ComPtr gBLAS; + ComPtr gTLASBuffer; + ComPtr gTLAS; + ComPtr gResultTexture; + ComPtr gResultTextureUAV; + + uint64_t lastTime = 0; + + // glm::vec3 lightDir = normalize(glm::vec3(10, 10, 10)); + // glm::vec3 lightColor = glm::vec3(1, 1, 1); + + glm::vec3 cameraPosition = glm::vec3(-2.53f, 2.72f, 4.3f); + float cameraOrientationAngles[2] = {-0.475f, -0.35f}; // Spherical angles (theta, phi). + + float translationScale = 0.5f; + float rotationScale = 0.01f; + + // In order to control camera movement, we will + // use good old WASD + bool wPressed = false; + bool aPressed = false; + bool sPressed = false; + bool dPressed = false; + + bool isMouseDown = false; + float lastMouseX = 0.0f; + float lastMouseY = 0.0f; + + void setKeyState(platform::KeyCode key, bool state) { - default: - break; - case platform::KeyCode::W: - wPressed = state; - break; - case platform::KeyCode::A: - aPressed = state; - break; - case platform::KeyCode::S: - sPressed = state; - break; - case platform::KeyCode::D: - dPressed = state; - break; + switch (key) + { + default: break; + case platform::KeyCode::W: wPressed = state; break; + case platform::KeyCode::A: aPressed = state; break; + case platform::KeyCode::S: sPressed = state; break; + case platform::KeyCode::D: dPressed = state; break; + } } -} -void onKeyDown(platform::KeyEventArgs args) { setKeyState(args.key, true); } -void onKeyUp(platform::KeyEventArgs args) { setKeyState(args.key, false); } + void onKeyDown(platform::KeyEventArgs args) { setKeyState(args.key, true); } + void onKeyUp(platform::KeyEventArgs args) { setKeyState(args.key, false); } -void onMouseDown(platform::MouseEventArgs args) -{ - isMouseDown = true; - lastMouseX = (float)args.x; - lastMouseY = (float)args.y; -} - -void onMouseMove(platform::MouseEventArgs args) -{ - if (isMouseDown) + void onMouseDown(platform::MouseEventArgs args) { - float deltaX = args.x - lastMouseX; - float deltaY = args.y - lastMouseY; - - cameraOrientationAngles[0] += -deltaX * rotationScale; - cameraOrientationAngles[1] += -deltaY * rotationScale; + isMouseDown = true; lastMouseX = (float)args.x; lastMouseY = (float)args.y; } -} -void onMouseUp(platform::MouseEventArgs args) { isMouseDown = false; } - -Slang::Result initialize() -{ - initializeBase("Ray Tracing", 1024, 768); - if (!isTestMode()) + void onMouseMove(platform::MouseEventArgs args) { - gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { onMouseMove(e); }; - gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { onMouseUp(e); }; - gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { onMouseDown(e); }; - gWindow->events.keyDown = [this](const platform::KeyEventArgs& e) { onKeyDown(e); }; - gWindow->events.keyUp = [this](const platform::KeyEventArgs& e) { onKeyUp(e); }; + if (isMouseDown) + { + float deltaX = args.x - lastMouseX; + float deltaY = args.y - lastMouseY; + + cameraOrientationAngles[0] += -deltaX * rotationScale; + cameraOrientationAngles[1] += -deltaY * rotationScale; + lastMouseX = (float)args.x; + lastMouseY = (float)args.y; + } } + void onMouseUp(platform::MouseEventArgs args) { isMouseDown = false; } - IBufferResource::Desc vertexBufferDesc; - vertexBufferDesc.type = IResource::Type::Buffer; - vertexBufferDesc.sizeInBytes = kVertexCount * sizeof(Vertex); - vertexBufferDesc.defaultState = ResourceState::ShaderResource; - gVertexBuffer = gDevice->createBufferResource(vertexBufferDesc, &kVertexData[0]); - if(!gVertexBuffer) return SLANG_FAIL; - - IBufferResource::Desc indexBufferDesc; - indexBufferDesc.type = IResource::Type::Buffer; - indexBufferDesc.sizeInBytes = kIndexCount * sizeof(int32_t); - indexBufferDesc.defaultState = ResourceState::ShaderResource; - gIndexBuffer = gDevice->createBufferResource(indexBufferDesc, &kIndexData[0]); - if (!gIndexBuffer) - return SLANG_FAIL; - - IBufferResource::Desc primitiveBufferDesc; - primitiveBufferDesc.type = IResource::Type::Buffer; - primitiveBufferDesc.sizeInBytes = kPrimitiveCount * sizeof(Primitive); - primitiveBufferDesc.elementSize = sizeof(Primitive); - primitiveBufferDesc.defaultState = ResourceState::ShaderResource; - gPrimitiveBuffer = gDevice->createBufferResource(primitiveBufferDesc, &kPrimitiveData[0]); - if (!gPrimitiveBuffer) - return SLANG_FAIL; - - IResourceView::Desc primitiveSRVDesc = {}; - primitiveSRVDesc.format = Format::Unknown; - primitiveSRVDesc.type = IResourceView::Type::ShaderResource; - gPrimitiveBufferSRV = gDevice->createBufferView(gPrimitiveBuffer, nullptr, primitiveSRVDesc); - - IBufferResource::Desc transformBufferDesc; - transformBufferDesc.type = IResource::Type::Buffer; - transformBufferDesc.sizeInBytes = sizeof(float) * 12; - transformBufferDesc.defaultState = ResourceState::ShaderResource; - float transformData[12] = { - 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}; - gTransformBuffer = gDevice->createBufferResource(transformBufferDesc, &transformData); - if (!gTransformBuffer) - return SLANG_FAIL; - // Build bottom level acceleration structure. + Slang::Result initialize() { - IAccelerationStructure::BuildInputs accelerationStructureBuildInputs; - IAccelerationStructure::PrebuildInfo accelerationStructurePrebuildInfo; - accelerationStructureBuildInputs.descCount = 1; - accelerationStructureBuildInputs.kind = IAccelerationStructure::Kind::BottomLevel; - accelerationStructureBuildInputs.flags = - IAccelerationStructure::BuildFlags::AllowCompaction; - IAccelerationStructure::GeometryDesc geomDesc; - geomDesc.flags = IAccelerationStructure::GeometryFlags::Opaque; - geomDesc.type = IAccelerationStructure::GeometryType::Triangles; - geomDesc.content.triangles.indexCount = kIndexCount; - geomDesc.content.triangles.indexData = gIndexBuffer->getDeviceAddress(); - geomDesc.content.triangles.indexFormat = Format::R32_UINT; - geomDesc.content.triangles.vertexCount = kVertexCount; - geomDesc.content.triangles.vertexData = gVertexBuffer->getDeviceAddress(); - geomDesc.content.triangles.vertexFormat = Format::R32G32B32_FLOAT; - geomDesc.content.triangles.vertexStride = sizeof(Vertex); - geomDesc.content.triangles.transform3x4 = gTransformBuffer->getDeviceAddress(); - accelerationStructureBuildInputs.geometryDescs = &geomDesc; - - // Query buffer size for acceleration structure build. - SLANG_RETURN_ON_FAIL(gDevice->getAccelerationStructurePrebuildInfo( - accelerationStructureBuildInputs, &accelerationStructurePrebuildInfo)); - // Allocate buffers for acceleration structure. - IBufferResource::Desc asDraftBufferDesc; - asDraftBufferDesc.type = IResource::Type::Buffer; - asDraftBufferDesc.defaultState = ResourceState::AccelerationStructure; - asDraftBufferDesc.sizeInBytes = accelerationStructurePrebuildInfo.resultDataMaxSize; - ComPtr draftBuffer = gDevice->createBufferResource(asDraftBufferDesc); - IBufferResource::Desc scratchBufferDesc; - scratchBufferDesc.type = IResource::Type::Buffer; - scratchBufferDesc.defaultState = ResourceState::UnorderedAccess; - scratchBufferDesc.sizeInBytes = accelerationStructurePrebuildInfo.scratchDataSize; - ComPtr scratchBuffer = gDevice->createBufferResource(scratchBufferDesc); - - // Build acceleration structure. - ComPtr compactedSizeQuery; - IQueryPool::Desc queryPoolDesc; - queryPoolDesc.count = 1; - queryPoolDesc.type = QueryType::AccelerationStructureCompactedSize; - SLANG_RETURN_ON_FAIL( - gDevice->createQueryPool(queryPoolDesc, compactedSizeQuery.writeRef())); - - ComPtr draftAS; - IAccelerationStructure::CreateDesc draftCreateDesc; - draftCreateDesc.buffer = draftBuffer; - draftCreateDesc.kind = IAccelerationStructure::Kind::BottomLevel; - draftCreateDesc.offset = 0; - draftCreateDesc.size = accelerationStructurePrebuildInfo.resultDataMaxSize; - SLANG_RETURN_ON_FAIL( - gDevice->createAccelerationStructure(draftCreateDesc, draftAS.writeRef())); - - compactedSizeQuery->reset(); - - auto commandBuffer = gTransientHeaps[0]->createCommandBuffer(); - auto encoder = commandBuffer->encodeRayTracingCommands(); - IAccelerationStructure::BuildDesc buildDesc = {}; - buildDesc.dest = draftAS; - buildDesc.inputs = accelerationStructureBuildInputs; - buildDesc.scratchData = scratchBuffer->getDeviceAddress(); - AccelerationStructureQueryDesc compactedSizeQueryDesc = {}; - compactedSizeQueryDesc.queryPool = compactedSizeQuery; - compactedSizeQueryDesc.queryType = QueryType::AccelerationStructureCompactedSize; - encoder->buildAccelerationStructure(buildDesc, 1, &compactedSizeQueryDesc); - encoder->endEncoding(); - commandBuffer->close(); - gQueue->executeCommandBuffer(commandBuffer); - gQueue->waitOnHost(); - - uint64_t compactedSize = 0; - compactedSizeQuery->getResult(0, 1, &compactedSize); - IBufferResource::Desc asBufferDesc; - asBufferDesc.type = IResource::Type::Buffer; - asBufferDesc.defaultState = ResourceState::AccelerationStructure; - asBufferDesc.sizeInBytes = (Size)compactedSize; - gBLASBuffer = gDevice->createBufferResource(asBufferDesc); - IAccelerationStructure::CreateDesc createDesc; - createDesc.buffer = gBLASBuffer; - createDesc.kind = IAccelerationStructure::Kind::BottomLevel; - createDesc.offset = 0; - createDesc.size = (Size)compactedSize; - gDevice->createAccelerationStructure(createDesc, gBLAS.writeRef()); - - commandBuffer = gTransientHeaps[0]->createCommandBuffer(); - encoder = commandBuffer->encodeRayTracingCommands(); - encoder->copyAccelerationStructure(gBLAS, draftAS, AccelerationStructureCopyMode::Compact); - encoder->endEncoding(); - commandBuffer->close(); - gQueue->executeCommandBuffer(commandBuffer); - gQueue->waitOnHost(); - } + initializeBase("Ray Tracing", 1024, 768); + + if (!isTestMode()) + { + gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) + { onMouseMove(e); }; + gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { onMouseUp(e); }; + gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) + { onMouseDown(e); }; + gWindow->events.keyDown = [this](const platform::KeyEventArgs& e) { onKeyDown(e); }; + gWindow->events.keyUp = [this](const platform::KeyEventArgs& e) { onKeyUp(e); }; + } + + IBufferResource::Desc vertexBufferDesc; + vertexBufferDesc.type = IResource::Type::Buffer; + vertexBufferDesc.sizeInBytes = kVertexCount * sizeof(Vertex); + vertexBufferDesc.defaultState = ResourceState::ShaderResource; + gVertexBuffer = gDevice->createBufferResource(vertexBufferDesc, &kVertexData[0]); + if (!gVertexBuffer) + return SLANG_FAIL; - // Build top level acceleration structure. - { - List instanceDescs; - instanceDescs.setCount(1); - instanceDescs[0].accelerationStructure = gBLAS->getDeviceAddress(); - instanceDescs[0].flags = - IAccelerationStructure::GeometryInstanceFlags::TriangleFacingCullDisable; - instanceDescs[0].instanceContributionToHitGroupIndex = 0; - instanceDescs[0].instanceID = 0; - instanceDescs[0].instanceMask = 0xFF; - float transformMatrix[] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}; - memcpy(&instanceDescs[0].transform[0][0], transformMatrix, sizeof(float) * 12); - - IBufferResource::Desc instanceBufferDesc; - instanceBufferDesc.type = IResource::Type::Buffer; - instanceBufferDesc.sizeInBytes = - instanceDescs.getCount() * sizeof(IAccelerationStructure::InstanceDesc); - instanceBufferDesc.defaultState = ResourceState::ShaderResource; - gInstanceBuffer = gDevice->createBufferResource(instanceBufferDesc, instanceDescs.getBuffer()); - if (!gInstanceBuffer) + IBufferResource::Desc indexBufferDesc; + indexBufferDesc.type = IResource::Type::Buffer; + indexBufferDesc.sizeInBytes = kIndexCount * sizeof(int32_t); + indexBufferDesc.defaultState = ResourceState::ShaderResource; + gIndexBuffer = gDevice->createBufferResource(indexBufferDesc, &kIndexData[0]); + if (!gIndexBuffer) return SLANG_FAIL; - IAccelerationStructure::BuildInputs accelerationStructureBuildInputs = {}; - IAccelerationStructure::PrebuildInfo accelerationStructurePrebuildInfo = {}; - accelerationStructureBuildInputs.descCount = 1; - accelerationStructureBuildInputs.kind = IAccelerationStructure::Kind::TopLevel; - accelerationStructureBuildInputs.instanceDescs = gInstanceBuffer->getDeviceAddress(); - - // Query buffer size for acceleration structure build. - SLANG_RETURN_ON_FAIL(gDevice->getAccelerationStructurePrebuildInfo( - accelerationStructureBuildInputs, &accelerationStructurePrebuildInfo)); - - IBufferResource::Desc asBufferDesc; - asBufferDesc.type = IResource::Type::Buffer; - asBufferDesc.defaultState = ResourceState::AccelerationStructure; - asBufferDesc.sizeInBytes = accelerationStructurePrebuildInfo.resultDataMaxSize; - gTLASBuffer = gDevice->createBufferResource(asBufferDesc); - - IBufferResource::Desc scratchBufferDesc; - scratchBufferDesc.type = IResource::Type::Buffer; - scratchBufferDesc.defaultState = ResourceState::UnorderedAccess; - scratchBufferDesc.sizeInBytes = accelerationStructurePrebuildInfo.scratchDataSize; - ComPtr scratchBuffer = gDevice->createBufferResource(scratchBufferDesc); - - IAccelerationStructure::CreateDesc createDesc; - createDesc.buffer = gTLASBuffer; - createDesc.kind = IAccelerationStructure::Kind::TopLevel; - createDesc.offset = 0; - createDesc.size = accelerationStructurePrebuildInfo.resultDataMaxSize; - SLANG_RETURN_ON_FAIL(gDevice->createAccelerationStructure(createDesc, gTLAS.writeRef())); - - auto commandBuffer = gTransientHeaps[0]->createCommandBuffer(); - auto encoder = commandBuffer->encodeRayTracingCommands(); - IAccelerationStructure::BuildDesc buildDesc = {}; - buildDesc.dest = gTLAS; - buildDesc.inputs = accelerationStructureBuildInputs; - buildDesc.scratchData = scratchBuffer->getDeviceAddress(); - encoder->buildAccelerationStructure(buildDesc, 0, nullptr); - encoder->endEncoding(); - commandBuffer->close(); - gQueue->executeCommandBuffer(commandBuffer); - gQueue->waitOnHost(); - } + IBufferResource::Desc primitiveBufferDesc; + primitiveBufferDesc.type = IResource::Type::Buffer; + primitiveBufferDesc.sizeInBytes = kPrimitiveCount * sizeof(Primitive); + primitiveBufferDesc.elementSize = sizeof(Primitive); + primitiveBufferDesc.defaultState = ResourceState::ShaderResource; + gPrimitiveBuffer = gDevice->createBufferResource(primitiveBufferDesc, &kPrimitiveData[0]); + if (!gPrimitiveBuffer) + return SLANG_FAIL; - IBufferResource::Desc fullScreenVertexBufferDesc; - fullScreenVertexBufferDesc.type = IResource::Type::Buffer; - fullScreenVertexBufferDesc.sizeInBytes = - FullScreenTriangle::kVertexCount * sizeof(FullScreenTriangle::Vertex); - fullScreenVertexBufferDesc.defaultState = ResourceState::VertexBuffer; - gFullScreenVertexBuffer = gDevice->createBufferResource( - fullScreenVertexBufferDesc, &FullScreenTriangle::kVertices[0]); - if (!gFullScreenVertexBuffer) - return SLANG_FAIL; - - InputElementDesc inputElements[] = { - {"POSITION", 0, Format::R32G32_FLOAT, offsetof(FullScreenTriangle::Vertex, position)}, - }; - auto inputLayout = gDevice->createInputLayout(sizeof(FullScreenTriangle::Vertex), &inputElements[0], SLANG_COUNT_OF(inputElements)); - if (!inputLayout) - return SLANG_FAIL; - - ComPtr shaderProgram; - SLANG_RETURN_ON_FAIL(loadShaderProgram(gDevice, false, shaderProgram.writeRef())); - GraphicsPipelineStateDesc desc; - desc.inputLayout = inputLayout; - desc.program = shaderProgram; - desc.framebufferLayout = gFramebufferLayout; - gPresentPipelineState = gDevice->createGraphicsPipelineState(desc); - if (!gPresentPipelineState) - return SLANG_FAIL; - - ComPtr computeProgram; - SLANG_RETURN_ON_FAIL(loadShaderProgram(gDevice, true, computeProgram.writeRef())); - ComputePipelineStateDesc computeDesc; - computeDesc.program = computeProgram; - gRenderPipelineState = gDevice->createComputePipelineState(computeDesc); - if (!gRenderPipelineState) - return SLANG_FAIL; - - createResultTexture(); - return SLANG_OK; -} - -void createResultTexture() -{ - ITextureResource::Desc resultTextureDesc = {}; - resultTextureDesc.type = IResource::Type::Texture2D; - resultTextureDesc.numMipLevels = 1; - resultTextureDesc.size.width = windowWidth; - resultTextureDesc.size.height = windowHeight; - resultTextureDesc.size.depth = 1; - resultTextureDesc.defaultState = ResourceState::UnorderedAccess; - resultTextureDesc.format = Format::R16G16B16A16_FLOAT; - gResultTexture = gDevice->createTextureResource(resultTextureDesc); - IResourceView::Desc resultUAVDesc = {}; - resultUAVDesc.format = resultTextureDesc.format; - resultUAVDesc.type = IResourceView::Type::UnorderedAccess; - gResultTextureUAV = gDevice->createTextureView(gResultTexture, resultUAVDesc); -} - -virtual void windowSizeChanged() override -{ - WindowedAppBase::windowSizeChanged(); - createResultTexture(); -} + IResourceView::Desc primitiveSRVDesc = {}; + primitiveSRVDesc.format = Format::Unknown; + primitiveSRVDesc.type = IResourceView::Type::ShaderResource; + gPrimitiveBufferSRV = + gDevice->createBufferView(gPrimitiveBuffer, nullptr, primitiveSRVDesc); + + IBufferResource::Desc transformBufferDesc; + transformBufferDesc.type = IResource::Type::Buffer; + transformBufferDesc.sizeInBytes = sizeof(float) * 12; + transformBufferDesc.defaultState = ResourceState::ShaderResource; + float transformData[12] = + {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}; + gTransformBuffer = gDevice->createBufferResource(transformBufferDesc, &transformData); + if (!gTransformBuffer) + return SLANG_FAIL; + // Build bottom level acceleration structure. + { + IAccelerationStructure::BuildInputs accelerationStructureBuildInputs; + IAccelerationStructure::PrebuildInfo accelerationStructurePrebuildInfo; + accelerationStructureBuildInputs.descCount = 1; + accelerationStructureBuildInputs.kind = IAccelerationStructure::Kind::BottomLevel; + accelerationStructureBuildInputs.flags = + IAccelerationStructure::BuildFlags::AllowCompaction; + IAccelerationStructure::GeometryDesc geomDesc; + geomDesc.flags = IAccelerationStructure::GeometryFlags::Opaque; + geomDesc.type = IAccelerationStructure::GeometryType::Triangles; + geomDesc.content.triangles.indexCount = kIndexCount; + geomDesc.content.triangles.indexData = gIndexBuffer->getDeviceAddress(); + geomDesc.content.triangles.indexFormat = Format::R32_UINT; + geomDesc.content.triangles.vertexCount = kVertexCount; + geomDesc.content.triangles.vertexData = gVertexBuffer->getDeviceAddress(); + geomDesc.content.triangles.vertexFormat = Format::R32G32B32_FLOAT; + geomDesc.content.triangles.vertexStride = sizeof(Vertex); + geomDesc.content.triangles.transform3x4 = gTransformBuffer->getDeviceAddress(); + accelerationStructureBuildInputs.geometryDescs = &geomDesc; + + // Query buffer size for acceleration structure build. + SLANG_RETURN_ON_FAIL(gDevice->getAccelerationStructurePrebuildInfo( + accelerationStructureBuildInputs, + &accelerationStructurePrebuildInfo)); + // Allocate buffers for acceleration structure. + IBufferResource::Desc asDraftBufferDesc; + asDraftBufferDesc.type = IResource::Type::Buffer; + asDraftBufferDesc.defaultState = ResourceState::AccelerationStructure; + asDraftBufferDesc.sizeInBytes = accelerationStructurePrebuildInfo.resultDataMaxSize; + ComPtr draftBuffer = gDevice->createBufferResource(asDraftBufferDesc); + IBufferResource::Desc scratchBufferDesc; + scratchBufferDesc.type = IResource::Type::Buffer; + scratchBufferDesc.defaultState = ResourceState::UnorderedAccess; + scratchBufferDesc.sizeInBytes = accelerationStructurePrebuildInfo.scratchDataSize; + ComPtr scratchBuffer = + gDevice->createBufferResource(scratchBufferDesc); + + // Build acceleration structure. + ComPtr compactedSizeQuery; + IQueryPool::Desc queryPoolDesc; + queryPoolDesc.count = 1; + queryPoolDesc.type = QueryType::AccelerationStructureCompactedSize; + SLANG_RETURN_ON_FAIL( + gDevice->createQueryPool(queryPoolDesc, compactedSizeQuery.writeRef())); + + ComPtr draftAS; + IAccelerationStructure::CreateDesc draftCreateDesc; + draftCreateDesc.buffer = draftBuffer; + draftCreateDesc.kind = IAccelerationStructure::Kind::BottomLevel; + draftCreateDesc.offset = 0; + draftCreateDesc.size = accelerationStructurePrebuildInfo.resultDataMaxSize; + SLANG_RETURN_ON_FAIL( + gDevice->createAccelerationStructure(draftCreateDesc, draftAS.writeRef())); + + compactedSizeQuery->reset(); + + auto commandBuffer = gTransientHeaps[0]->createCommandBuffer(); + auto encoder = commandBuffer->encodeRayTracingCommands(); + IAccelerationStructure::BuildDesc buildDesc = {}; + buildDesc.dest = draftAS; + buildDesc.inputs = accelerationStructureBuildInputs; + buildDesc.scratchData = scratchBuffer->getDeviceAddress(); + AccelerationStructureQueryDesc compactedSizeQueryDesc = {}; + compactedSizeQueryDesc.queryPool = compactedSizeQuery; + compactedSizeQueryDesc.queryType = QueryType::AccelerationStructureCompactedSize; + encoder->buildAccelerationStructure(buildDesc, 1, &compactedSizeQueryDesc); + encoder->endEncoding(); + commandBuffer->close(); + gQueue->executeCommandBuffer(commandBuffer); + gQueue->waitOnHost(); + + uint64_t compactedSize = 0; + compactedSizeQuery->getResult(0, 1, &compactedSize); + IBufferResource::Desc asBufferDesc; + asBufferDesc.type = IResource::Type::Buffer; + asBufferDesc.defaultState = ResourceState::AccelerationStructure; + asBufferDesc.sizeInBytes = (Size)compactedSize; + gBLASBuffer = gDevice->createBufferResource(asBufferDesc); + IAccelerationStructure::CreateDesc createDesc; + createDesc.buffer = gBLASBuffer; + createDesc.kind = IAccelerationStructure::Kind::BottomLevel; + createDesc.offset = 0; + createDesc.size = (Size)compactedSize; + gDevice->createAccelerationStructure(createDesc, gBLAS.writeRef()); + + commandBuffer = gTransientHeaps[0]->createCommandBuffer(); + encoder = commandBuffer->encodeRayTracingCommands(); + encoder->copyAccelerationStructure( + gBLAS, + draftAS, + AccelerationStructureCopyMode::Compact); + encoder->endEncoding(); + commandBuffer->close(); + gQueue->executeCommandBuffer(commandBuffer); + gQueue->waitOnHost(); + } + + // Build top level acceleration structure. + { + List instanceDescs; + instanceDescs.setCount(1); + instanceDescs[0].accelerationStructure = gBLAS->getDeviceAddress(); + instanceDescs[0].flags = + IAccelerationStructure::GeometryInstanceFlags::TriangleFacingCullDisable; + instanceDescs[0].instanceContributionToHitGroupIndex = 0; + instanceDescs[0].instanceID = 0; + instanceDescs[0].instanceMask = 0xFF; + float transformMatrix[] = + {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}; + memcpy(&instanceDescs[0].transform[0][0], transformMatrix, sizeof(float) * 12); + + IBufferResource::Desc instanceBufferDesc; + instanceBufferDesc.type = IResource::Type::Buffer; + instanceBufferDesc.sizeInBytes = + instanceDescs.getCount() * sizeof(IAccelerationStructure::InstanceDesc); + instanceBufferDesc.defaultState = ResourceState::ShaderResource; + gInstanceBuffer = + gDevice->createBufferResource(instanceBufferDesc, instanceDescs.getBuffer()); + if (!gInstanceBuffer) + return SLANG_FAIL; + + IAccelerationStructure::BuildInputs accelerationStructureBuildInputs = {}; + IAccelerationStructure::PrebuildInfo accelerationStructurePrebuildInfo = {}; + accelerationStructureBuildInputs.descCount = 1; + accelerationStructureBuildInputs.kind = IAccelerationStructure::Kind::TopLevel; + accelerationStructureBuildInputs.instanceDescs = gInstanceBuffer->getDeviceAddress(); + + // Query buffer size for acceleration structure build. + SLANG_RETURN_ON_FAIL(gDevice->getAccelerationStructurePrebuildInfo( + accelerationStructureBuildInputs, + &accelerationStructurePrebuildInfo)); + + IBufferResource::Desc asBufferDesc; + asBufferDesc.type = IResource::Type::Buffer; + asBufferDesc.defaultState = ResourceState::AccelerationStructure; + asBufferDesc.sizeInBytes = accelerationStructurePrebuildInfo.resultDataMaxSize; + gTLASBuffer = gDevice->createBufferResource(asBufferDesc); + + IBufferResource::Desc scratchBufferDesc; + scratchBufferDesc.type = IResource::Type::Buffer; + scratchBufferDesc.defaultState = ResourceState::UnorderedAccess; + scratchBufferDesc.sizeInBytes = accelerationStructurePrebuildInfo.scratchDataSize; + ComPtr scratchBuffer = + gDevice->createBufferResource(scratchBufferDesc); + + IAccelerationStructure::CreateDesc createDesc; + createDesc.buffer = gTLASBuffer; + createDesc.kind = IAccelerationStructure::Kind::TopLevel; + createDesc.offset = 0; + createDesc.size = accelerationStructurePrebuildInfo.resultDataMaxSize; + SLANG_RETURN_ON_FAIL( + gDevice->createAccelerationStructure(createDesc, gTLAS.writeRef())); + + auto commandBuffer = gTransientHeaps[0]->createCommandBuffer(); + auto encoder = commandBuffer->encodeRayTracingCommands(); + IAccelerationStructure::BuildDesc buildDesc = {}; + buildDesc.dest = gTLAS; + buildDesc.inputs = accelerationStructureBuildInputs; + buildDesc.scratchData = scratchBuffer->getDeviceAddress(); + encoder->buildAccelerationStructure(buildDesc, 0, nullptr); + encoder->endEncoding(); + commandBuffer->close(); + gQueue->executeCommandBuffer(commandBuffer); + gQueue->waitOnHost(); + } + + IBufferResource::Desc fullScreenVertexBufferDesc; + fullScreenVertexBufferDesc.type = IResource::Type::Buffer; + fullScreenVertexBufferDesc.sizeInBytes = + FullScreenTriangle::kVertexCount * sizeof(FullScreenTriangle::Vertex); + fullScreenVertexBufferDesc.defaultState = ResourceState::VertexBuffer; + gFullScreenVertexBuffer = gDevice->createBufferResource( + fullScreenVertexBufferDesc, + &FullScreenTriangle::kVertices[0]); + if (!gFullScreenVertexBuffer) + return SLANG_FAIL; -glm::vec3 getVectorFromSphericalAngles(float theta, float phi) -{ - auto sinTheta = sin(theta); - auto cosTheta = cos(theta); - auto sinPhi = sin(phi); - auto cosPhi = cos(phi); - return glm::vec3(-sinTheta * cosPhi, sinPhi, -cosTheta * cosPhi); -} -void updateUniforms() -{ - gUniforms.screenWidth = (float)windowWidth; - gUniforms.screenHeight = (float)windowHeight; - if (!lastTime) - lastTime = getCurrentTime(); - uint64_t currentTime = getCurrentTime(); - float deltaTime = float(double(currentTime - lastTime) / double(getTimerFrequency())); - lastTime = currentTime; - - auto camDir = - getVectorFromSphericalAngles(cameraOrientationAngles[0], cameraOrientationAngles[1]); - auto camUp = getVectorFromSphericalAngles( - cameraOrientationAngles[0], cameraOrientationAngles[1] + glm::pi() * 0.5f); - auto camRight = glm::cross(camDir, camUp); - - glm::vec3 movement = glm::vec3(0); - if (wPressed) - movement += camDir; - if (sPressed) - movement -= camDir; - if (aPressed) - movement -= camRight; - if (dPressed) - movement += camRight; - - cameraPosition += deltaTime * translationScale * movement; - - memcpy(gUniforms.cameraDir, &camDir, sizeof(float) * 3); - memcpy(gUniforms.cameraUp, &camUp, sizeof(float) * 3); - memcpy(gUniforms.cameraRight, &camRight, sizeof(float) * 3); - memcpy(gUniforms.cameraPosition, &cameraPosition, sizeof(float) * 3); - auto lightDir = glm::normalize(glm::vec3(1.0f, 3.0f, 2.0f)); - memcpy(gUniforms.lightDir, &lightDir, sizeof(float) * 3); -} - -virtual void renderFrame(int frameBufferIndex) override -{ - updateUniforms(); + InputElementDesc inputElements[] = { + {"POSITION", 0, Format::R32G32_FLOAT, offsetof(FullScreenTriangle::Vertex, position)}, + }; + auto inputLayout = gDevice->createInputLayout( + sizeof(FullScreenTriangle::Vertex), + &inputElements[0], + SLANG_COUNT_OF(inputElements)); + if (!inputLayout) + return SLANG_FAIL; + + ComPtr shaderProgram; + SLANG_RETURN_ON_FAIL(loadShaderProgram(gDevice, false, shaderProgram.writeRef())); + GraphicsPipelineStateDesc desc; + desc.inputLayout = inputLayout; + desc.program = shaderProgram; + desc.framebufferLayout = gFramebufferLayout; + gPresentPipelineState = gDevice->createGraphicsPipelineState(desc); + if (!gPresentPipelineState) + return SLANG_FAIL; + + ComPtr computeProgram; + SLANG_RETURN_ON_FAIL(loadShaderProgram(gDevice, true, computeProgram.writeRef())); + ComputePipelineStateDesc computeDesc; + computeDesc.program = computeProgram; + gRenderPipelineState = gDevice->createComputePipelineState(computeDesc); + if (!gRenderPipelineState) + return SLANG_FAIL; + + createResultTexture(); + return SLANG_OK; + } + + void createResultTexture() { - ComPtr renderCommandBuffer = - gTransientHeaps[frameBufferIndex]->createCommandBuffer(); - auto renderEncoder = renderCommandBuffer->encodeComputeCommands(); - auto rootObject = renderEncoder->bindPipeline(gRenderPipelineState); - auto cursor = ShaderCursor(rootObject->getEntryPoint(0)); - cursor["resultTexture"].setResource(gResultTextureUAV); - cursor["uniforms"].setData(&gUniforms, sizeof(Uniforms)); - cursor["sceneBVH"].setResource(gTLAS); - cursor["primitiveBuffer"].setResource(gPrimitiveBufferSRV); - renderEncoder->dispatchCompute((windowWidth + 15) / 16, (windowHeight + 15) / 16, 1); - renderEncoder->endEncoding(); - renderCommandBuffer->close(); - gQueue->executeCommandBuffer(renderCommandBuffer); + ITextureResource::Desc resultTextureDesc = {}; + resultTextureDesc.type = IResource::Type::Texture2D; + resultTextureDesc.numMipLevels = 1; + resultTextureDesc.size.width = windowWidth; + resultTextureDesc.size.height = windowHeight; + resultTextureDesc.size.depth = 1; + resultTextureDesc.defaultState = ResourceState::UnorderedAccess; + resultTextureDesc.format = Format::R16G16B16A16_FLOAT; + gResultTexture = gDevice->createTextureResource(resultTextureDesc); + IResourceView::Desc resultUAVDesc = {}; + resultUAVDesc.format = resultTextureDesc.format; + resultUAVDesc.type = IResourceView::Type::UnorderedAccess; + gResultTextureUAV = gDevice->createTextureView(gResultTexture, resultUAVDesc); } + virtual void windowSizeChanged() override { - ComPtr presentCommandBuffer = - gTransientHeaps[frameBufferIndex]->createCommandBuffer(); - auto presentEncoder = presentCommandBuffer->encodeRenderCommands( - gRenderPass, gFramebuffers[frameBufferIndex]); - gfx::Viewport viewport = {}; - viewport.maxZ = 1.0f; - viewport.extentX = (float)windowWidth; - viewport.extentY = (float)windowHeight; - presentEncoder->setViewportAndScissor(viewport); - auto rootObject = presentEncoder->bindPipeline(gPresentPipelineState); - auto cursor = ShaderCursor(rootObject->getEntryPoint(1)); - cursor["t"].setResource(gResultTextureUAV); - presentEncoder->setVertexBuffer( - 0, gFullScreenVertexBuffer); - presentEncoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); - presentEncoder->draw(3); - presentEncoder->endEncoding(); - presentCommandBuffer->close(); - gQueue->executeCommandBuffer(presentCommandBuffer); + WindowedAppBase::windowSizeChanged(); + createResultTexture(); } - if (!isTestMode()) + glm::vec3 getVectorFromSphericalAngles(float theta, float phi) { - // With that, we are done drawing for one frame, and ready for the next. - // - gSwapchain->present(); + auto sinTheta = sin(theta); + auto cosTheta = cos(theta); + auto sinPhi = sin(phi); + auto cosPhi = cos(phi); + return glm::vec3(-sinTheta * cosPhi, sinPhi, -cosTheta * cosPhi); + } + void updateUniforms() + { + gUniforms.screenWidth = (float)windowWidth; + gUniforms.screenHeight = (float)windowHeight; + if (!lastTime) + lastTime = getCurrentTime(); + uint64_t currentTime = getCurrentTime(); + float deltaTime = float(double(currentTime - lastTime) / double(getTimerFrequency())); + lastTime = currentTime; + + auto camDir = + getVectorFromSphericalAngles(cameraOrientationAngles[0], cameraOrientationAngles[1]); + auto camUp = getVectorFromSphericalAngles( + cameraOrientationAngles[0], + cameraOrientationAngles[1] + glm::pi() * 0.5f); + auto camRight = glm::cross(camDir, camUp); + + glm::vec3 movement = glm::vec3(0); + if (wPressed) + movement += camDir; + if (sPressed) + movement -= camDir; + if (aPressed) + movement -= camRight; + if (dPressed) + movement += camRight; + + cameraPosition += deltaTime * translationScale * movement; + + memcpy(gUniforms.cameraDir, &camDir, sizeof(float) * 3); + memcpy(gUniforms.cameraUp, &camUp, sizeof(float) * 3); + memcpy(gUniforms.cameraRight, &camRight, sizeof(float) * 3); + memcpy(gUniforms.cameraPosition, &cameraPosition, sizeof(float) * 3); + auto lightDir = glm::normalize(glm::vec3(1.0f, 3.0f, 2.0f)); + memcpy(gUniforms.lightDir, &lightDir, sizeof(float) * 3); } -} + virtual void renderFrame(int frameBufferIndex) override + { + updateUniforms(); + { + ComPtr renderCommandBuffer = + gTransientHeaps[frameBufferIndex]->createCommandBuffer(); + auto renderEncoder = renderCommandBuffer->encodeComputeCommands(); + auto rootObject = renderEncoder->bindPipeline(gRenderPipelineState); + auto cursor = ShaderCursor(rootObject->getEntryPoint(0)); + cursor["resultTexture"].setResource(gResultTextureUAV); + cursor["uniforms"].setData(&gUniforms, sizeof(Uniforms)); + cursor["sceneBVH"].setResource(gTLAS); + cursor["primitiveBuffer"].setResource(gPrimitiveBufferSRV); + renderEncoder->dispatchCompute((windowWidth + 15) / 16, (windowHeight + 15) / 16, 1); + renderEncoder->endEncoding(); + renderCommandBuffer->close(); + gQueue->executeCommandBuffer(renderCommandBuffer); + } + + { + ComPtr presentCommandBuffer = + gTransientHeaps[frameBufferIndex]->createCommandBuffer(); + auto presentEncoder = presentCommandBuffer->encodeRenderCommands( + gRenderPass, + gFramebuffers[frameBufferIndex]); + gfx::Viewport viewport = {}; + viewport.maxZ = 1.0f; + viewport.extentX = (float)windowWidth; + viewport.extentY = (float)windowHeight; + presentEncoder->setViewportAndScissor(viewport); + auto rootObject = presentEncoder->bindPipeline(gPresentPipelineState); + auto cursor = ShaderCursor(rootObject->getEntryPoint(1)); + cursor["t"].setResource(gResultTextureUAV); + presentEncoder->setVertexBuffer(0, gFullScreenVertexBuffer); + presentEncoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); + presentEncoder->draw(3); + presentEncoder->endEncoding(); + presentCommandBuffer->close(); + gQueue->executeCommandBuffer(presentCommandBuffer); + } + + if (!isTestMode()) + { + // With that, we are done drawing for one frame, and ready for the next. + // + gSwapchain->present(); + } + } }; // This macro instantiates an appropriate main function to diff --git a/examples/shader-object/main.cpp b/examples/shader-object/main.cpp index 603278bcf..74d81604b 100644 --- a/examples/shader-object/main.cpp +++ b/examples/shader-object/main.cpp @@ -8,14 +8,14 @@ // simplifies shader specialization and parameter binding when using `interface` typed // shader parameters. // -#include "slang.h" #include "slang-com-ptr.h" +#include "slang.h" using Slang::ComPtr; -#include "slang-gfx.h" +#include "examples/example-base/example-base.h" #include "gfx-util/shader-cursor.h" +#include "slang-gfx.h" #include "source/core/slang-basic.h" -#include "examples/example-base/example-base.h" using namespace gfx; @@ -37,7 +37,7 @@ Result loadShaderProgram( // creates a Slang compilation session for us, so we just grab and use it here. ComPtr slangSession; SLANG_RETURN_ON_FAIL(device->getSlangSession(slangSession.writeRef())); - + // Once the session has been obtained, we can start loading code into it. // // The simplest way to load code is by calling `loadModule` with the name of a Slang @@ -61,7 +61,7 @@ Result loadShaderProgram( Slang::String path = resourceBase.resolveResource("shader-object.slang"); slang::IModule* module = slangSession->loadModule(path.getBuffer(), diagnosticsBlob.writeRef()); diagnoseIfNeeded(diagnosticsBlob); - if(!module) + if (!module) return SLANG_FAIL; // Loading the `shader-object` module will compile and check all the shader code in it, @@ -74,13 +74,13 @@ Result loadShaderProgram( // is no umambiguous way for the compiler to know which functions represent entry // points when it parses your code via `loadModule()`. // - char const* computeEntryPointName = "computeMain"; + char const* computeEntryPointName = "computeMain"; ComPtr computeEntryPoint; SLANG_RETURN_ON_FAIL( module->findEntryPointByName(computeEntryPointName, computeEntryPoint.writeRef())); - + // At this point we have a few different Slang API objects that represent - // pieces of our code: `module`, `vertexEntryPoint`, and `fragmentEntryPoint`. + // pieces of our code: `module`, `vertexEntryPoint`, and `fragmentEntryPoint`. // // A single Slang module could contain many different entry points (e.g., // four vertex entry points, three fragment entry points, and two compute @@ -177,10 +177,8 @@ int main(int argc, char* argv[]) bufferDesc.memoryType = MemoryType::DeviceLocal; ComPtr numbersBuffer; - SLANG_RETURN_ON_FAIL(device->createBufferResource( - bufferDesc, - (void*)initialData, - numbersBuffer.writeRef())); + SLANG_RETURN_ON_FAIL( + device->createBufferResource(bufferDesc, (void*)initialData, numbersBuffer.writeRef())); // Create a resource view for the buffer. ComPtr bufferView; @@ -217,7 +215,9 @@ int main(int argc, char* argv[]) // Now we can use this type to create a shader object that can be bound to the root object. ComPtr transformer; SLANG_RETURN_ON_FAIL(device->createShaderObject( - addTransformerType, ShaderObjectContainerType::None, transformer.writeRef())); + addTransformerType, + ShaderObjectContainerType::None, + transformer.writeRef())); // Set the `c` field of the `AddTransformer`. float c = 1.0f; gfx::ShaderCursor(transformer).getPath("c").setData(&c, sizeof(float)); @@ -244,7 +244,10 @@ int main(int argc, char* argv[]) // Read back the results. ComPtr resultBlob; SLANG_RETURN_ON_FAIL(device->readBufferResource( - numbersBuffer, 0, numberCount * sizeof(float), resultBlob.writeRef())); + numbersBuffer, + 0, + numberCount * sizeof(float), + resultBlob.writeRef())); auto result = reinterpret_cast(resultBlob->getBufferPointer()); for (int i = 0; i < numberCount; i++) printf("%f\n", result[i]); diff --git a/examples/shader-toy/main.cpp b/examples/shader-toy/main.cpp index 13a79c7ee..38212099e 100644 --- a/examples/shader-toy/main.cpp +++ b/examples/shader-toy/main.cpp @@ -10,8 +10,8 @@ // This example uses the Slang C/C++ API, alonmg with its optional type // for managing COM-style reference-counted pointers. // -#include "slang.h" #include "slang-com-ptr.h" +#include "slang.h" using Slang::ComPtr; // This example uses a graphics API abstraction layer that is implemented inside @@ -19,12 +19,12 @@ using Slang::ComPtr; // this layer is *not* required or assumed when using the Slang language, // compiler, and API. // +#include "examples/example-base/example-base.h" #include "slang-gfx.h" +#include "source/core/slang-basic.h" #include "tools/gfx-util/shader-cursor.h" -#include "tools/platform/window.h" #include "tools/platform/performance-counter.h" -#include "examples/example-base/example-base.h" -#include "source/core/slang-basic.h" +#include "tools/platform/window.h" #include @@ -43,15 +43,17 @@ struct FullScreenTriangle float position[2]; }; - enum { kVertexCount = 3 }; + enum + { + kVertexCount = 3 + }; static const Vertex kVertices[kVertexCount]; }; -const FullScreenTriangle::Vertex FullScreenTriangle::kVertices[FullScreenTriangle::kVertexCount] = -{ - { { -1, -1 } }, - { { -1, 3 } }, - { { 3, -1 } }, +const FullScreenTriangle::Vertex FullScreenTriangle::kVertices[FullScreenTriangle::kVertexCount] = { + {{-1, -1}}, + {{-1, 3}}, + {{3, -1}}, }; // The application itself will be encapsulated in a C++ `struct` type @@ -60,333 +62,336 @@ const FullScreenTriangle::Vertex FullScreenTriangle::kVertices[FullScreenTriangl struct ShaderToyApp : public WindowedAppBase { -// The uniform data used by the shader is defined here as a simple -// POD ("plain old data") type. -// -// Note: This type must match the declaration of `ShaderToyUniforms` -// in the file `shader-toy.slang`. -// -// An application could instead use a shared header file to define -// this type, or use Slang's reflection capabilities to allocate -// and set parameters at runtime. For this simple example we did -// the expedient thing of having distinct Slang and C++ declarations. -// -struct Uniforms -{ - float iMouse[4]; - float iResolution[2]; - float iTime; -}; - -// The main interesting part of the host application code is where we -// load, compile, inspect, and compose the Slang shader code. -// -Result loadShaderProgram(gfx::IDevice* device, ComPtr& outShaderProgram) -{ - // We need to obatin a compilation session (`slang::ISession`) that will provide - // a scope to all the compilation and loading of code we do. - // - // Our example application uses the `gfx` graphics API abstraction layer, which already - // creates a Slang compilation session for us, so we just grab and use it here. - ComPtr slangSession; - SLANG_RETURN_ON_FAIL(device->getSlangSession(slangSession.writeRef())); - - // Once the session has been obtained, we can start loading code into it. - // - // The simplest way to load code is by calling `loadModule` with the name of a Slang - // module. A call to `loadModule("MyStuff")` will behave more or less as if you - // wrote: - // - // import MyStuff; - // - // In a Slang shader file. The compiler will use its search paths to try to locate - // `MyModule.slang`, then compile and load that file. If a matching module had - // already been loaded previously, that would be used directly. + // The uniform data used by the shader is defined here as a simple + // POD ("plain old data") type. // - // Note: The only interesting wrinkle here is that our file is named `shader-toy` with - // a hyphen in it, so the name is not directly usable as an identifier in Slang code. - // Instead, when trying to import this module in the context of Slang code, a user - // needs to replace the hyphens with underscores: + // Note: This type must match the declaration of `ShaderToyUniforms` + // in the file `shader-toy.slang`. // - // import shader_toy; + // An application could instead use a shared header file to define + // this type, or use Slang's reflection capabilities to allocate + // and set parameters at runtime. For this simple example we did + // the expedient thing of having distinct Slang and C++ declarations. // - ComPtr diagnosticsBlob; - Slang::String shaderToyPath = resourceBase.resolveResource("shader-toy.slang"); - slang::IModule* module = slangSession->loadModule(shaderToyPath.getBuffer(), diagnosticsBlob.writeRef()); - diagnoseIfNeeded(diagnosticsBlob); - if(!module) - return SLANG_FAIL; - - // Loading the `shader-toy` module will compile and check all the shader code in it, - // including the shader entry points we want to use. Now that the module is loaded - // we can look up those entry points by name. - // - // Note: If you are using this `loadModule` approach to load your shader code it is - // important to tag your entry point functions with the `[shader("...")]` attribute - // (e.g., `[shader("vertex")] void vertexMain(...)`). Without that information there - // is no umambiguous way for the compiler to know which functions represent entry - // points when it parses your code via `loadModule()`. - // - char const* vertexEntryPointName = "vertexMain"; - char const* fragmentEntryPointName = "fragmentMain"; - // - ComPtr vertexEntryPoint; - SLANG_RETURN_ON_FAIL(module->findEntryPointByName(vertexEntryPointName, vertexEntryPoint.writeRef())); - // - ComPtr fragmentEntryPoint; - SLANG_RETURN_ON_FAIL(module->findEntryPointByName(fragmentEntryPointName, fragmentEntryPoint.writeRef())); + struct Uniforms + { + float iMouse[4]; + float iResolution[2]; + float iTime; + }; - // At this point we have a few different Slang API objects that represent - // pieces of our code: `module`, `vertexEntryPoint`, and `fragmentEntryPoint`. - // - // A single Slang module could contain many different entry points (e.g., - // four vertex entry points, three fragment entry points, and two compute - // shaders), and before we try to generate output code for our target API - // we need to identify which entry points we plan to use together. - // - // Modules and entry points are both examples of *component types* in the - // Slang API. The API also provides a way to build a *composite* out of - // other pieces, and that is what we are going to do with our module - // and entry points. - // - Slang::List componentTypes; - componentTypes.add(module); - - // Later on when we go to extract compiled kernel code for our vertex - // and fragment shaders, we will need to make use of their order within - // the composition, so we will record the relative ordering of the entry - // points here as we add them. - int entryPointCount = 0; - int vertexEntryPointIndex = entryPointCount++; - componentTypes.add(vertexEntryPoint); - - int fragmentEntryPointIndex = entryPointCount++; - componentTypes.add(fragmentEntryPoint); - - // Actually creating the composite component type is a single operation - // on the Slang session, but the operation could potentially fail if - // something about the composite was invalid (e.g., you are trying to - // combine multiple copies of the same module), so we need to deal - // with the possibility of diagnostic output. - // - ComPtr composedProgram; - SlangResult result = slangSession->createCompositeComponentType( - componentTypes.getBuffer(), - componentTypes.getCount(), - composedProgram.writeRef(), - diagnosticsBlob.writeRef()); - diagnoseIfNeeded(diagnosticsBlob); - SLANG_RETURN_ON_FAIL(result); - - // At this point, `composedProgram` represents the shader program - // we want to run, and the vertex and fragment shader there have - // been checked. - // - // We could use the Slang reflection API on `composedProgram` at this - // point to query things like the locations and offsets of the - // various uniform parameters, textures, etc. + // The main interesting part of the host application code is where we + // load, compile, inspect, and compose the Slang shader code. // - // What *cannot* be done yet at this point is actually generating - // kernel code, because `composedProgram` includes a generic type - // parameter as part of the `fragmentMain` entry point: - // - // void fragmentMain(...) - // - // Our next task is to load code for a type we'd like to plug in - // for `T` there. - // - // Because Slang supports modular programming, there is no requirement - // that a type we want to plug in for `T` has to come from the - // same module, and to demonstrate that we will load a different - // module to provide the effect type we will plug in. - // - const char* effectTypeName = "ExampleEffect"; - Slang::String effectModulePath = resourceBase.resolveResource("example-effect.slang"); - slang::IModule* effectModule = slangSession->loadModule(effectModulePath.getBuffer(), diagnosticsBlob.writeRef()); - diagnoseIfNeeded(diagnosticsBlob); - if(!module) - return SLANG_FAIL; - - // Once we've loaded the code module that defines out effect type, - // we can look it up by name using the reflection information on - // the module. - // - // Note: A future version of the Slang API will support enumerating - // the types declared in a module so that we do not have to hard-code - // the name here. - // - auto effectType = effectModule->getLayout()->findTypeByName(effectTypeName); + Result loadShaderProgram(gfx::IDevice* device, ComPtr& outShaderProgram) + { + // We need to obatin a compilation session (`slang::ISession`) that will provide + // a scope to all the compilation and loading of code we do. + // + // Our example application uses the `gfx` graphics API abstraction layer, which already + // creates a Slang compilation session for us, so we just grab and use it here. + ComPtr slangSession; + SLANG_RETURN_ON_FAIL(device->getSlangSession(slangSession.writeRef())); - // Now that we have the `effectType` we want to plug in to our generic - // shader, we need to specialize the shader to that type. - // - // Because a shader program could have zero or more specialization parameters, - // we need to build up an array of specialization arguments. - // - Slang::List specializationArgs; + // Once the session has been obtained, we can start loading code into it. + // + // The simplest way to load code is by calling `loadModule` with the name of a Slang + // module. A call to `loadModule("MyStuff")` will behave more or less as if you + // wrote: + // + // import MyStuff; + // + // In a Slang shader file. The compiler will use its search paths to try to locate + // `MyModule.slang`, then compile and load that file. If a matching module had + // already been loaded previously, that would be used directly. + // + // Note: The only interesting wrinkle here is that our file is named `shader-toy` with + // a hyphen in it, so the name is not directly usable as an identifier in Slang code. + // Instead, when trying to import this module in the context of Slang code, a user + // needs to replace the hyphens with underscores: + // + // import shader_toy; + // + ComPtr diagnosticsBlob; + Slang::String shaderToyPath = resourceBase.resolveResource("shader-toy.slang"); + slang::IModule* module = + slangSession->loadModule(shaderToyPath.getBuffer(), diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + if (!module) + return SLANG_FAIL; + + // Loading the `shader-toy` module will compile and check all the shader code in it, + // including the shader entry points we want to use. Now that the module is loaded + // we can look up those entry points by name. + // + // Note: If you are using this `loadModule` approach to load your shader code it is + // important to tag your entry point functions with the `[shader("...")]` attribute + // (e.g., `[shader("vertex")] void vertexMain(...)`). Without that information there + // is no umambiguous way for the compiler to know which functions represent entry + // points when it parses your code via `loadModule()`. + // + char const* vertexEntryPointName = "vertexMain"; + char const* fragmentEntryPointName = "fragmentMain"; + // + ComPtr vertexEntryPoint; + SLANG_RETURN_ON_FAIL( + module->findEntryPointByName(vertexEntryPointName, vertexEntryPoint.writeRef())); + // + ComPtr fragmentEntryPoint; + SLANG_RETURN_ON_FAIL( + module->findEntryPointByName(fragmentEntryPointName, fragmentEntryPoint.writeRef())); - { - // In our case, we only have a single specialization argument we plan - // to use, and it is a type argument. + // At this point we have a few different Slang API objects that represent + // pieces of our code: `module`, `vertexEntryPoint`, and `fragmentEntryPoint`. + // + // A single Slang module could contain many different entry points (e.g., + // four vertex entry points, three fragment entry points, and two compute + // shaders), and before we try to generate output code for our target API + // we need to identify which entry points we plan to use together. + // + // Modules and entry points are both examples of *component types* in the + // Slang API. The API also provides a way to build a *composite* out of + // other pieces, and that is what we are going to do with our module + // and entry points. + // + Slang::List componentTypes; + componentTypes.add(module); + + // Later on when we go to extract compiled kernel code for our vertex + // and fragment shaders, we will need to make use of their order within + // the composition, so we will record the relative ordering of the entry + // points here as we add them. + int entryPointCount = 0; + int vertexEntryPointIndex = entryPointCount++; + componentTypes.add(vertexEntryPoint); + + int fragmentEntryPointIndex = entryPointCount++; + componentTypes.add(fragmentEntryPoint); + + // Actually creating the composite component type is a single operation + // on the Slang session, but the operation could potentially fail if + // something about the composite was invalid (e.g., you are trying to + // combine multiple copies of the same module), so we need to deal + // with the possibility of diagnostic output. + // + ComPtr composedProgram; + SlangResult result = slangSession->createCompositeComponentType( + componentTypes.getBuffer(), + componentTypes.getCount(), + composedProgram.writeRef(), + diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + SLANG_RETURN_ON_FAIL(result); + + // At this point, `composedProgram` represents the shader program + // we want to run, and the vertex and fragment shader there have + // been checked. + // + // We could use the Slang reflection API on `composedProgram` at this + // point to query things like the locations and offsets of the + // various uniform parameters, textures, etc. + // + // What *cannot* be done yet at this point is actually generating + // kernel code, because `composedProgram` includes a generic type + // parameter as part of the `fragmentMain` entry point: + // + // void fragmentMain(...) + // + // Our next task is to load code for a type we'd like to plug in + // for `T` there. + // + // Because Slang supports modular programming, there is no requirement + // that a type we want to plug in for `T` has to come from the + // same module, and to demonstrate that we will load a different + // module to provide the effect type we will plug in. + // + const char* effectTypeName = "ExampleEffect"; + Slang::String effectModulePath = resourceBase.resolveResource("example-effect.slang"); + slang::IModule* effectModule = + slangSession->loadModule(effectModulePath.getBuffer(), diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + if (!module) + return SLANG_FAIL; + + // Once we've loaded the code module that defines out effect type, + // we can look it up by name using the reflection information on + // the module. + // + // Note: A future version of the Slang API will support enumerating + // the types declared in a module so that we do not have to hard-code + // the name here. + // + auto effectType = effectModule->getLayout()->findTypeByName(effectTypeName); + + // Now that we have the `effectType` we want to plug in to our generic + // shader, we need to specialize the shader to that type. + // + // Because a shader program could have zero or more specialization parameters, + // we need to build up an array of specialization arguments. // - slang::SpecializationArg effectTypeArg; - effectTypeArg.kind = slang::SpecializationArg::Kind::Type; - effectTypeArg.type = effectType; - specializationArgs.add(effectTypeArg); + Slang::List specializationArgs; + + { + // In our case, we only have a single specialization argument we plan + // to use, and it is a type argument. + // + slang::SpecializationArg effectTypeArg; + effectTypeArg.kind = slang::SpecializationArg::Kind::Type; + effectTypeArg.type = effectType; + specializationArgs.add(effectTypeArg); + } + + // Specialization of a component type is a single Slang API call, but + // we need to deal with the possibility of diagnostic output on failure. + // For example, if we tried to specialize the shader program to a + // type like `int` that doesn't support the `IShaderToyImageShader` interface, + // this is the step where we'd get an error message saying so. + // + ComPtr specializedProgram; + result = composedProgram->specialize( + specializationArgs.getBuffer(), + specializationArgs.getCount(), + specializedProgram.writeRef(), + diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + SLANG_RETURN_ON_FAIL(result); + + // At this point we have a specialized shader program that represents our + // intention to run the `vertexMain` and `fragmentMain` entry points, + // specialized to the `ExampleEffect` type we loaded. + // + // We can now *link* the program, which ensures that all of the code that + // it transitively depends on has been pulled together into a single + // component type. + // + ComPtr linkedProgram; + result = specializedProgram->link(linkedProgram.writeRef(), diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + SLANG_RETURN_ON_FAIL(result); + + gfx::IShaderProgram::Desc programDesc = {}; + programDesc.slangGlobalScope = linkedProgram.get(); + auto shaderProgram = device->createProgram(programDesc); + outShaderProgram = shaderProgram; + return SLANG_OK; } - // Specialization of a component type is a single Slang API call, but - // we need to deal with the possibility of diagnostic output on failure. - // For example, if we tried to specialize the shader program to a - // type like `int` that doesn't support the `IShaderToyImageShader` interface, - // this is the step where we'd get an error message saying so. - // - ComPtr specializedProgram; - result = composedProgram->specialize( - specializationArgs.getBuffer(), - specializationArgs.getCount(), - specializedProgram.writeRef(), - diagnosticsBlob.writeRef()); - diagnoseIfNeeded(diagnosticsBlob); - SLANG_RETURN_ON_FAIL(result); - - // At this point we have a specialized shader program that represents our - // intention to run the `vertexMain` and `fragmentMain` entry points, - // specialized to the `ExampleEffect` type we loaded. - // - // We can now *link* the program, which ensures that all of the code that - // it transitively depends on has been pulled together into a single - // component type. - // - ComPtr linkedProgram; - result = specializedProgram->link( - linkedProgram.writeRef(), - diagnosticsBlob.writeRef()); - diagnoseIfNeeded(diagnosticsBlob); - SLANG_RETURN_ON_FAIL(result); - - gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangGlobalScope = linkedProgram.get(); - auto shaderProgram = device->createProgram(programDesc); - outShaderProgram = shaderProgram; - return SLANG_OK; -} - -ComPtr gShaderProgram; -ComPtr gPipelineState; -ComPtr gVertexBuffer; - -Result initialize() -{ - initializeBase("Shader Toy", 1024, 768); - gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { handleEvent(e); }; - gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { handleEvent(e); }; - gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { handleEvent(e); }; + ComPtr gShaderProgram; + ComPtr gPipelineState; + ComPtr gVertexBuffer; - InputElementDesc inputElements[] = { - { "POSITION", 0, Format::R32G32_FLOAT, offsetof(FullScreenTriangle::Vertex, position) }, - }; - auto inputLayout = gDevice->createInputLayout( - sizeof(FullScreenTriangle::Vertex), - &inputElements[0], - SLANG_COUNT_OF(inputElements)); - if(!inputLayout) return SLANG_FAIL; - - IBufferResource::Desc vertexBufferDesc; - vertexBufferDesc.type = IResource::Type::Buffer; - vertexBufferDesc.sizeInBytes = FullScreenTriangle::kVertexCount * sizeof(FullScreenTriangle::Vertex); - vertexBufferDesc.defaultState = ResourceState::VertexBuffer; - gVertexBuffer = gDevice->createBufferResource( - vertexBufferDesc, - &FullScreenTriangle::kVertices[0]); - if(!gVertexBuffer) return SLANG_FAIL; - - SLANG_RETURN_ON_FAIL(loadShaderProgram(gDevice, gShaderProgram)); - - // Create pipeline. - GraphicsPipelineStateDesc desc; - desc.inputLayout = inputLayout; - desc.program = gShaderProgram; - desc.framebufferLayout = gFramebufferLayout; - auto pipelineState = gDevice->createGraphicsPipelineState(desc); - if (!pipelineState) - return SLANG_FAIL; - - gPipelineState = pipelineState; - - return SLANG_OK; -} - -bool wasMouseDown = false; -bool isMouseDown = false; -float lastMouseX = 0.0f; -float lastMouseY = 0.0f; -float clickMouseX = 0.0f; -float clickMouseY = 0.0f; - -bool firstTime = true; -platform::TimePoint startTime; - -virtual void renderFrame(int frameIndex) override -{ - auto commandBuffer = gTransientHeaps[frameIndex]->createCommandBuffer(); - if( firstTime ) + Result initialize() { - startTime = platform::PerformanceCounter::now(); - firstTime = false; + initializeBase("Shader Toy", 1024, 768); + gWindow->events.mouseMove = [this](const platform::MouseEventArgs& e) { handleEvent(e); }; + gWindow->events.mouseUp = [this](const platform::MouseEventArgs& e) { handleEvent(e); }; + gWindow->events.mouseDown = [this](const platform::MouseEventArgs& e) { handleEvent(e); }; + + InputElementDesc inputElements[] = { + {"POSITION", 0, Format::R32G32_FLOAT, offsetof(FullScreenTriangle::Vertex, position)}, + }; + auto inputLayout = gDevice->createInputLayout( + sizeof(FullScreenTriangle::Vertex), + &inputElements[0], + SLANG_COUNT_OF(inputElements)); + if (!inputLayout) + return SLANG_FAIL; + + IBufferResource::Desc vertexBufferDesc; + vertexBufferDesc.type = IResource::Type::Buffer; + vertexBufferDesc.sizeInBytes = + FullScreenTriangle::kVertexCount * sizeof(FullScreenTriangle::Vertex); + vertexBufferDesc.defaultState = ResourceState::VertexBuffer; + gVertexBuffer = + gDevice->createBufferResource(vertexBufferDesc, &FullScreenTriangle::kVertices[0]); + if (!gVertexBuffer) + return SLANG_FAIL; + + SLANG_RETURN_ON_FAIL(loadShaderProgram(gDevice, gShaderProgram)); + + // Create pipeline. + GraphicsPipelineStateDesc desc; + desc.inputLayout = inputLayout; + desc.program = gShaderProgram; + desc.framebufferLayout = gFramebufferLayout; + auto pipelineState = gDevice->createGraphicsPipelineState(desc); + if (!pipelineState) + return SLANG_FAIL; + + gPipelineState = pipelineState; + + return SLANG_OK; } - // Update uniform buffer. + bool wasMouseDown = false; + bool isMouseDown = false; + float lastMouseX = 0.0f; + float lastMouseY = 0.0f; + float clickMouseX = 0.0f; + float clickMouseY = 0.0f; + + bool firstTime = true; + platform::TimePoint startTime; - Uniforms uniforms = {}; + virtual void renderFrame(int frameIndex) override { - bool isMouseClick = isMouseDown && !wasMouseDown; - wasMouseDown = isMouseDown; + auto commandBuffer = gTransientHeaps[frameIndex]->createCommandBuffer(); + if (firstTime) + { + startTime = platform::PerformanceCounter::now(); + firstTime = false; + } + + // Update uniform buffer. - if( isMouseClick ) + Uniforms uniforms = {}; { - clickMouseX = lastMouseX; - clickMouseY = lastMouseY; + bool isMouseClick = isMouseDown && !wasMouseDown; + wasMouseDown = isMouseDown; + + if (isMouseClick) + { + clickMouseX = lastMouseX; + clickMouseY = lastMouseY; + } + + uniforms.iMouse[0] = lastMouseX; + uniforms.iMouse[1] = lastMouseY; + uniforms.iMouse[2] = isMouseDown ? clickMouseX : -clickMouseX; + uniforms.iMouse[3] = isMouseClick ? clickMouseY : -clickMouseY; + uniforms.iTime = platform::PerformanceCounter::getElapsedTimeInSeconds(startTime); + uniforms.iResolution[0] = float(windowWidth); + uniforms.iResolution[1] = float(windowHeight); } - uniforms.iMouse[0] = lastMouseX; - uniforms.iMouse[1] = lastMouseY; - uniforms.iMouse[2] = isMouseDown ? clickMouseX : -clickMouseX; - uniforms.iMouse[3] = isMouseClick ? clickMouseY : -clickMouseY; - uniforms.iTime = platform::PerformanceCounter::getElapsedTimeInSeconds(startTime); - uniforms.iResolution[0] = float(windowWidth); - uniforms.iResolution[1] = float(windowHeight); + // Encode render commands. + auto encoder = commandBuffer->encodeRenderCommands(gRenderPass, gFramebuffers[frameIndex]); + + gfx::Viewport viewport = {}; + viewport.maxZ = 1.0f; + viewport.extentX = (float)windowWidth; + viewport.extentY = (float)windowHeight; + encoder->setViewportAndScissor(viewport); + auto rootObject = encoder->bindPipeline(gPipelineState); + auto constantBuffer = rootObject->getObject(ShaderOffset()); + constantBuffer->setData(ShaderOffset(), &uniforms, sizeof(uniforms)); + + encoder->setVertexBuffer(0, gVertexBuffer); + encoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); + encoder->draw(3); + encoder->endEncoding(); + commandBuffer->close(); + + gQueue->executeCommandBuffer(commandBuffer); + gSwapchain->present(); + } + void handleEvent(const platform::MouseEventArgs& event) + { + isMouseDown = ((int)event.buttons & (int)platform::ButtonState::Enum::LeftButton) != 0; + lastMouseX = (float)event.x; + lastMouseY = (float)event.y; } - - // Encode render commands. - auto encoder = commandBuffer->encodeRenderCommands(gRenderPass, gFramebuffers[frameIndex]); - - gfx::Viewport viewport = {}; - viewport.maxZ = 1.0f; - viewport.extentX = (float)windowWidth; - viewport.extentY = (float)windowHeight; - encoder->setViewportAndScissor(viewport); - auto rootObject = encoder->bindPipeline(gPipelineState); - auto constantBuffer = rootObject->getObject(ShaderOffset()); - constantBuffer->setData(ShaderOffset(), &uniforms, sizeof(uniforms)); - - encoder->setVertexBuffer(0, gVertexBuffer); - encoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); - encoder->draw(3); - encoder->endEncoding(); - commandBuffer->close(); - - gQueue->executeCommandBuffer(commandBuffer); - gSwapchain->present(); -} - -void handleEvent(const platform::MouseEventArgs& event) -{ - isMouseDown = ((int)event.buttons & (int)platform::ButtonState::Enum::LeftButton) != 0; - lastMouseX = (float)event.x; - lastMouseY = (float)event.y; -} }; // This macro instantiates an appropriate main function to diff --git a/examples/triangle/main.cpp b/examples/triangle/main.cpp index 88c55c416..d5f929bf2 100644 --- a/examples/triangle/main.cpp +++ b/examples/triangle/main.cpp @@ -32,12 +32,12 @@ // with Slang may depend on an application/engine making certain // design choices in their abstraction layer. // -#include "slang-gfx.h" +#include "examples/example-base/example-base.h" #include "gfx-util/shader-cursor.h" -#include "tools/platform/window.h" #include "slang-com-ptr.h" +#include "slang-gfx.h" #include "source/core/slang-basic.h" -#include "examples/example-base/example-base.h" +#include "tools/platform/window.h" using namespace gfx; using namespace Slang; @@ -55,11 +55,10 @@ struct Vertex }; static const int kVertexCount = 3; -static const Vertex kVertexData[kVertexCount] = -{ - { { 0, 0, 0.5 }, { 1, 0, 0 } }, - { { 0, 1, 0.5 }, { 0, 0, 1 } }, - { { 1, 0, 0.5 }, { 0, 1, 0 } }, +static const Vertex kVertexData[kVertexCount] = { + {{0, 0, 0.5}, {1, 0, 0}}, + {{0, 1, 0.5}, {0, 0, 1}}, + {{1, 0, 0.5}, {0, 1, 0}}, }; // The example application will be implemented as a `struct`, so that @@ -68,338 +67,340 @@ static const Vertex kVertexData[kVertexCount] = struct HelloWorld : public WindowedAppBase { -// Many Slang API functions return detailed diagnostic information -// (error messages, warnings, etc.) as a "blob" of data, or return -// a null blob pointer instead if there were no issues. -// -// For convenience, we define a subroutine that will dump the information -// in a diagnostic blob if one is produced, and skip it otherwise. -// -void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob) -{ - if( diagnosticsBlob != nullptr ) - { - printf("%s", (const char*) diagnosticsBlob->getBufferPointer()); - } -} - -// The main task an application cares about is compiling shader code -// from souce (if needed) and loading it through the chosen graphics API. -// -// In addition, an application may want to receive reflection information -// about the program, which is what a `slang::ProgramLayout` provides. -// -gfx::Result loadShaderProgram( - gfx::IDevice* device, - gfx::IShaderProgram** outProgram) -{ - // We need to obatin a compilation session (`slang::ISession`) that will provide - // a scope to all the compilation and loading of code we do. - // - // Our example application uses the `gfx` graphics API abstraction layer, which already - // creates a Slang compilation session for us, so we just grab and use it here. - ComPtr slangSession; - slangSession = device->getSlangSession(); - - // We can now start loading code into the slang session. - // - // The simplest way to load code is by calling `loadModule` with the name of a Slang - // module. A call to `loadModule("MyStuff")` will behave more or less as if you - // wrote: - // - // import MyStuff; - // - // In a Slang shader file. The compiler will use its search paths to try to locate - // `MyModule.slang`, then compile and load that file. If a matching module had - // already been loaded previously, that would be used directly. + // Many Slang API functions return detailed diagnostic information + // (error messages, warnings, etc.) as a "blob" of data, or return + // a null blob pointer instead if there were no issues. // - ComPtr diagnosticsBlob; - Slang::String path = resourceBase.resolveResource("shaders.slang"); - slang::IModule* module = slangSession->loadModule(path.getBuffer(), diagnosticsBlob.writeRef()); - diagnoseIfNeeded(diagnosticsBlob); - if(!module) - return SLANG_FAIL; - - // Loading the `shaders` module will compile and check all the shader code in it, - // including the shader entry points we want to use. Now that the module is loaded - // we can look up those entry points by name. + // For convenience, we define a subroutine that will dump the information + // in a diagnostic blob if one is produced, and skip it otherwise. // - // Note: If you are using this `loadModule` approach to load your shader code it is - // important to tag your entry point functions with the `[shader("...")]` attribute - // (e.g., `[shader("vertex")] void vertexMain(...)`). Without that information there - // is no umambiguous way for the compiler to know which functions represent entry - // points when it parses your code via `loadModule()`. - // - ComPtr vertexEntryPoint; - SLANG_RETURN_ON_FAIL(module->findEntryPointByName("vertexMain", vertexEntryPoint.writeRef())); - // - ComPtr fragmentEntryPoint; - SLANG_RETURN_ON_FAIL(module->findEntryPointByName("fragmentMain", fragmentEntryPoint.writeRef())); + void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob) + { + if (diagnosticsBlob != nullptr) + { + printf("%s", (const char*)diagnosticsBlob->getBufferPointer()); + } + } - // At this point we have a few different Slang API objects that represent - // pieces of our code: `module`, `vertexEntryPoint`, and `fragmentEntryPoint`. - // - // A single Slang module could contain many different entry points (e.g., - // four vertex entry points, three fragment entry points, and two compute - // shaders), and before we try to generate output code for our target API - // we need to identify which entry points we plan to use together. - // - // Modules and entry points are both examples of *component types* in the - // Slang API. The API also provides a way to build a *composite* out of - // other pieces, and that is what we are going to do with our module - // and entry points. - // - Slang::List componentTypes; - componentTypes.add(module); - - // Later on when we go to extract compiled kernel code for our vertex - // and fragment shaders, we will need to make use of their order within - // the composition, so we will record the relative ordering of the entry - // points here as we add them. - int entryPointCount = 0; - int vertexEntryPointIndex = entryPointCount++; - componentTypes.add(vertexEntryPoint); - - int fragmentEntryPointIndex = entryPointCount++; - componentTypes.add(fragmentEntryPoint); - - // Actually creating the composite component type is a single operation - // on the Slang session, but the operation could potentially fail if - // something about the composite was invalid (e.g., you are trying to - // combine multiple copies of the same module), so we need to deal - // with the possibility of diagnostic output. + // The main task an application cares about is compiling shader code + // from souce (if needed) and loading it through the chosen graphics API. // - ComPtr linkedProgram; - SlangResult result = slangSession->createCompositeComponentType( - componentTypes.getBuffer(), - componentTypes.getCount(), - linkedProgram.writeRef(), - diagnosticsBlob.writeRef()); - diagnoseIfNeeded(diagnosticsBlob); - SLANG_RETURN_ON_FAIL(result); - - // Once we've described the particular composition of entry points - // that we want to compile, we defer to the graphics API layer - // to extract compiled kernel code and load it into the API-specific - // program representation. + // In addition, an application may want to receive reflection information + // about the program, which is what a `slang::ProgramLayout` provides. // - gfx::IShaderProgram::Desc programDesc = {}; - programDesc.slangGlobalScope = linkedProgram; - SLANG_RETURN_ON_FAIL(device->createProgram(programDesc, outProgram)); - - if (isTestMode()) + gfx::Result loadShaderProgram(gfx::IDevice* device, gfx::IShaderProgram** outProgram) { - printEntrypointHashes(entryPointCount, 1, linkedProgram); - } + // We need to obatin a compilation session (`slang::ISession`) that will provide + // a scope to all the compilation and loading of code we do. + // + // Our example application uses the `gfx` graphics API abstraction layer, which already + // creates a Slang compilation session for us, so we just grab and use it here. + ComPtr slangSession; + slangSession = device->getSlangSession(); - return SLANG_OK; -} + // We can now start loading code into the slang session. + // + // The simplest way to load code is by calling `loadModule` with the name of a Slang + // module. A call to `loadModule("MyStuff")` will behave more or less as if you + // wrote: + // + // import MyStuff; + // + // In a Slang shader file. The compiler will use its search paths to try to locate + // `MyModule.slang`, then compile and load that file. If a matching module had + // already been loaded previously, that would be used directly. + // + ComPtr diagnosticsBlob; + Slang::String path = resourceBase.resolveResource("shaders.slang"); + slang::IModule* module = + slangSession->loadModule(path.getBuffer(), diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + if (!module) + return SLANG_FAIL; + + // Loading the `shaders` module will compile and check all the shader code in it, + // including the shader entry points we want to use. Now that the module is loaded + // we can look up those entry points by name. + // + // Note: If you are using this `loadModule` approach to load your shader code it is + // important to tag your entry point functions with the `[shader("...")]` attribute + // (e.g., `[shader("vertex")] void vertexMain(...)`). Without that information there + // is no umambiguous way for the compiler to know which functions represent entry + // points when it parses your code via `loadModule()`. + // + ComPtr vertexEntryPoint; + SLANG_RETURN_ON_FAIL( + module->findEntryPointByName("vertexMain", vertexEntryPoint.writeRef())); + // + ComPtr fragmentEntryPoint; + SLANG_RETURN_ON_FAIL( + module->findEntryPointByName("fragmentMain", fragmentEntryPoint.writeRef())); -// -// The above function shows the core of what is required to use the -// Slang API as a simple compiler (e.g., a drop-in replacement for -// fxc or dxc). -// -// The rest of this file implements an extremely simple rendering application -// that will execute the vertex/fragment shaders loaded with the function -// we have just defined. -// + // At this point we have a few different Slang API objects that represent + // pieces of our code: `module`, `vertexEntryPoint`, and `fragmentEntryPoint`. + // + // A single Slang module could contain many different entry points (e.g., + // four vertex entry points, three fragment entry points, and two compute + // shaders), and before we try to generate output code for our target API + // we need to identify which entry points we plan to use together. + // + // Modules and entry points are both examples of *component types* in the + // Slang API. The API also provides a way to build a *composite* out of + // other pieces, and that is what we are going to do with our module + // and entry points. + // + Slang::List componentTypes; + componentTypes.add(module); + + // Later on when we go to extract compiled kernel code for our vertex + // and fragment shaders, we will need to make use of their order within + // the composition, so we will record the relative ordering of the entry + // points here as we add them. + int entryPointCount = 0; + int vertexEntryPointIndex = entryPointCount++; + componentTypes.add(vertexEntryPoint); + + int fragmentEntryPointIndex = entryPointCount++; + componentTypes.add(fragmentEntryPoint); + + // Actually creating the composite component type is a single operation + // on the Slang session, but the operation could potentially fail if + // something about the composite was invalid (e.g., you are trying to + // combine multiple copies of the same module), so we need to deal + // with the possibility of diagnostic output. + // + ComPtr linkedProgram; + SlangResult result = slangSession->createCompositeComponentType( + componentTypes.getBuffer(), + componentTypes.getCount(), + linkedProgram.writeRef(), + diagnosticsBlob.writeRef()); + diagnoseIfNeeded(diagnosticsBlob); + SLANG_RETURN_ON_FAIL(result); + + // Once we've described the particular composition of entry points + // that we want to compile, we defer to the graphics API layer + // to extract compiled kernel code and load it into the API-specific + // program representation. + // + gfx::IShaderProgram::Desc programDesc = {}; + programDesc.slangGlobalScope = linkedProgram; + SLANG_RETURN_ON_FAIL(device->createProgram(programDesc, outProgram)); -// We will define global variables for the various platform and -// graphics API objects that our application needs: -// -// As a reminder, *none* of these are Slang API objects. All -// of them come from the utility library we are using to simplify -// building an example program. -// -ComPtr gPipelineState; -ComPtr gVertexBuffer; + if (isTestMode()) + { + printEntrypointHashes(entryPointCount, 1, linkedProgram); + } -// Now that we've covered the function that actually loads and -// compiles our Slang shade code, we can go through the rest -// of the application code without as much commentary. -// -Slang::Result initialize() -{ - // Create a window for our application to render into. - // - initializeBase("hello-world", 1024, 768); + return SLANG_OK; + } - // We will create objects needed to configur the "input assembler" - // (IA) stage of the D3D pipeline. // - // First, we create an input layout: + // The above function shows the core of what is required to use the + // Slang API as a simple compiler (e.g., a drop-in replacement for + // fxc or dxc). // - InputElementDesc inputElements[] = { - { "POSITION", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, position) }, - { "COLOR", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, color) }, - }; - auto inputLayout = gDevice->createInputLayout( - sizeof(Vertex), - &inputElements[0], - 2); - if(!inputLayout) return SLANG_FAIL; - - // Next we allocate a vertex buffer for our pre-initialized - // vertex data. + // The rest of this file implements an extremely simple rendering application + // that will execute the vertex/fragment shaders loaded with the function + // we have just defined. // - IBufferResource::Desc vertexBufferDesc; - vertexBufferDesc.type = IResource::Type::Buffer; - vertexBufferDesc.sizeInBytes = kVertexCount * sizeof(Vertex); - vertexBufferDesc.defaultState = ResourceState::VertexBuffer; - gVertexBuffer = gDevice->createBufferResource(vertexBufferDesc, &kVertexData[0]); - if(!gVertexBuffer) return SLANG_FAIL; - - // Now we will use our `loadShaderProgram` function to load - // the code from `shaders.slang` into the graphics API. - // - ComPtr shaderProgram; - SLANG_RETURN_ON_FAIL(loadShaderProgram(gDevice, shaderProgram.writeRef())); - // Following the D3D12/Vulkan style of API, we need a pipeline state object - // (PSO) to encapsulate the configuration of the overall graphics pipeline. + // We will define global variables for the various platform and + // graphics API objects that our application needs: // - GraphicsPipelineStateDesc desc; - desc.inputLayout = inputLayout; - desc.program = shaderProgram; - desc.framebufferLayout = gFramebufferLayout; - auto pipelineState = gDevice->createGraphicsPipelineState(desc); - if (!pipelineState) - return SLANG_FAIL; - - gPipelineState = pipelineState; - - return SLANG_OK; -} - -// With the initialization out of the way, we can now turn our attention -// to the per-frame rendering logic. As with the initialization, there is -// nothing really Slang-specific here, so the commentary doesn't need -// to be very detailed. -// -virtual void renderFrame(int frameBufferIndex) override -{ - ComPtr commandBuffer = gTransientHeaps[frameBufferIndex]->createCommandBuffer(); - auto renderEncoder = commandBuffer->encodeRenderCommands(gRenderPass, gFramebuffers[frameBufferIndex]); - - gfx::Viewport viewport = {}; - viewport.maxZ = 1.0f; - viewport.extentX = (float)windowWidth; - viewport.extentY = (float)windowHeight; - renderEncoder->setViewportAndScissor(viewport); - - // In order to bind shader parameters to the pipeline, we need - // to know how those parameters were assigned to locations/bindings/registers - // for the target graphics API. + // As a reminder, *none* of these are Slang API objects. All + // of them come from the utility library we are using to simplify + // building an example program. // - // The Slang compiler assigns locations to parameters in a deterministic - // fashion, so it is possible for a programmer to hard-code locations - // into their application code that will match up with their shaders. - // - // Hard-coding of locations can become intractable as an application needs - // to support more different target platforms and graphics APIs, as well - // as more shaders with different specialized variants. - // - // Rather than rely on hard-coded locations, our examples will make use of - // reflection information provided by the Slang compiler (see `programLayout` - // above), and our example graphics API layer will translate that reflection - // information into a layout for a "root shader object." - // - // The root object will store values/bindings for all of the parameters in - // the `IShaderProgram` used to create the pipeline state. At a conceptual - // level we can think of `rootObject` as representing the "global scope" of - // the shader program that was loaded; it has entries for each global shader - // parameter that was declared. - // - // Readers who are familiar with D3D12 or Vulkan might think of this root - // layout as being similar in spirit to a "root signature" or "pipeline layout." - // - // We start parameter binding by binding the pipeline state in command encoder. - // This method will return a transient root shader object for us to write our - // shader parameters into. - // - auto rootObject = renderEncoder->bindPipeline(gPipelineState); + ComPtr gPipelineState; + ComPtr gVertexBuffer; - // We will update the model-view-projection matrix that is passed - // into the shader code via the `Uniforms` buffer on a per-frame - // basis, even though the data that is loaded does not change - // per-frame (we always use an identity matrix). + // Now that we've covered the function that actually loads and + // compiles our Slang shade code, we can go through the rest + // of the application code without as much commentary. // - auto deviceInfo = gDevice->getDeviceInfo(); + Slang::Result initialize() + { + // Create a window for our application to render into. + // + initializeBase("hello-world", 1024, 768); - // We know that `rootObject` is a root shader object created - // from our program, and that it is set up to hold values for - // all the parameter of that program. In order to actually - // set values, we need to be able to look up the location - // of speciic parameter that we want to set. - // - // Our example graphics API layer supports this operation - // with the idea of a *shader cursor* which can be thought - // of as pointing "into" a particular shader object at - // some location/offset. This design choice abstracts over - // the many ways that different platforms and APIs represent - // the necessary offset information. - // - // We construct an initial shader cursor that points at the - // entire shader program. You can think of this as akin to - // a diretory path of `/` for the root directory in a file - // system. - // - ShaderCursor rootCursor(rootObject); - // - // Next, we use a convenience overload of `operator[]` to - // navigate from the root cursor down to the parameter we - // want to set. - // - // The operation `rootCursor["Uniforms"]` looks up the - // offset/location of the global shader parameter `Uniforms` - // (which is a uniform/constant buffer), and the subsequent - // `["modelViewProjection"]` step navigates from there down - // to the member named `modelViewProjection` in that buffer. - // - // Once we have formed a cursor that "points" at the - // model-view projection matrix, we can set its data directly. - // - rootCursor["Uniforms"]["modelViewProjection"].setData( - deviceInfo.identityProjectionMatrix, sizeof(float) * 16); - // - // Some readers might be concerned about the performance o - // the above operations because of the use of strings. For - // those readers, here are two things to note: - // - // * While these `operator[]` steps do need to perform string - // comparisons, they do *not* make copies of the strings or - // perform any heap allocation. - // - // * There are other overloads of `operator[]` that use the - // *index* of a parameter/field instead of its name, and those - // operations have fixed/constant overhead and perform no - // string comparisons. The indices used are independent of - // the target platform and graphics API, and can thus be - // hard-coded even in cross-platform code. - // + // We will create objects needed to configur the "input assembler" + // (IA) stage of the D3D pipeline. + // + // First, we create an input layout: + // + InputElementDesc inputElements[] = { + {"POSITION", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, position)}, + {"COLOR", 0, Format::R32G32B32_FLOAT, offsetof(Vertex, color)}, + }; + auto inputLayout = gDevice->createInputLayout(sizeof(Vertex), &inputElements[0], 2); + if (!inputLayout) + return SLANG_FAIL; + + // Next we allocate a vertex buffer for our pre-initialized + // vertex data. + // + IBufferResource::Desc vertexBufferDesc; + vertexBufferDesc.type = IResource::Type::Buffer; + vertexBufferDesc.sizeInBytes = kVertexCount * sizeof(Vertex); + vertexBufferDesc.defaultState = ResourceState::VertexBuffer; + gVertexBuffer = gDevice->createBufferResource(vertexBufferDesc, &kVertexData[0]); + if (!gVertexBuffer) + return SLANG_FAIL; + + // Now we will use our `loadShaderProgram` function to load + // the code from `shaders.slang` into the graphics API. + // + ComPtr shaderProgram; + SLANG_RETURN_ON_FAIL(loadShaderProgram(gDevice, shaderProgram.writeRef())); - // We also need to set up a few pieces of fixed-function pipeline - // state that are not bound by the pipeline state above. - // - renderEncoder->setVertexBuffer(0, gVertexBuffer); - renderEncoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); + // Following the D3D12/Vulkan style of API, we need a pipeline state object + // (PSO) to encapsulate the configuration of the overall graphics pipeline. + // + GraphicsPipelineStateDesc desc; + desc.inputLayout = inputLayout; + desc.program = shaderProgram; + desc.framebufferLayout = gFramebufferLayout; + auto pipelineState = gDevice->createGraphicsPipelineState(desc); + if (!pipelineState) + return SLANG_FAIL; - // Finally, we are ready to issue a draw call for a single triangle. - // - renderEncoder->draw(3); - renderEncoder->endEncoding(); - commandBuffer->close(); - gQueue->executeCommandBuffer(commandBuffer); + gPipelineState = pipelineState; + + return SLANG_OK; + } - if (!isTestMode()) + // With the initialization out of the way, we can now turn our attention + // to the per-frame rendering logic. As with the initialization, there is + // nothing really Slang-specific here, so the commentary doesn't need + // to be very detailed. + // + virtual void renderFrame(int frameBufferIndex) override { - // With that, we are done drawing for one frame, and ready for the next. + ComPtr commandBuffer = + gTransientHeaps[frameBufferIndex]->createCommandBuffer(); + auto renderEncoder = + commandBuffer->encodeRenderCommands(gRenderPass, gFramebuffers[frameBufferIndex]); + + gfx::Viewport viewport = {}; + viewport.maxZ = 1.0f; + viewport.extentX = (float)windowWidth; + viewport.extentY = (float)windowHeight; + renderEncoder->setViewportAndScissor(viewport); + + // In order to bind shader parameters to the pipeline, we need + // to know how those parameters were assigned to locations/bindings/registers + // for the target graphics API. // - gSwapchain->present(); - } -} + // The Slang compiler assigns locations to parameters in a deterministic + // fashion, so it is possible for a programmer to hard-code locations + // into their application code that will match up with their shaders. + // + // Hard-coding of locations can become intractable as an application needs + // to support more different target platforms and graphics APIs, as well + // as more shaders with different specialized variants. + // + // Rather than rely on hard-coded locations, our examples will make use of + // reflection information provided by the Slang compiler (see `programLayout` + // above), and our example graphics API layer will translate that reflection + // information into a layout for a "root shader object." + // + // The root object will store values/bindings for all of the parameters in + // the `IShaderProgram` used to create the pipeline state. At a conceptual + // level we can think of `rootObject` as representing the "global scope" of + // the shader program that was loaded; it has entries for each global shader + // parameter that was declared. + // + // Readers who are familiar with D3D12 or Vulkan might think of this root + // layout as being similar in spirit to a "root signature" or "pipeline layout." + // + // We start parameter binding by binding the pipeline state in command encoder. + // This method will return a transient root shader object for us to write our + // shader parameters into. + // + auto rootObject = renderEncoder->bindPipeline(gPipelineState); + + // We will update the model-view-projection matrix that is passed + // into the shader code via the `Uniforms` buffer on a per-frame + // basis, even though the data that is loaded does not change + // per-frame (we always use an identity matrix). + // + auto deviceInfo = gDevice->getDeviceInfo(); + // We know that `rootObject` is a root shader object created + // from our program, and that it is set up to hold values for + // all the parameter of that program. In order to actually + // set values, we need to be able to look up the location + // of speciic parameter that we want to set. + // + // Our example graphics API layer supports this operation + // with the idea of a *shader cursor* which can be thought + // of as pointing "into" a particular shader object at + // some location/offset. This design choice abstracts over + // the many ways that different platforms and APIs represent + // the necessary offset information. + // + // We construct an initial shader cursor that points at the + // entire shader program. You can think of this as akin to + // a diretory path of `/` for the root directory in a file + // system. + // + ShaderCursor rootCursor(rootObject); + // + // Next, we use a convenience overload of `operator[]` to + // navigate from the root cursor down to the parameter we + // want to set. + // + // The operation `rootCursor["Uniforms"]` looks up the + // offset/location of the global shader parameter `Uniforms` + // (which is a uniform/constant buffer), and the subsequent + // `["modelViewProjection"]` step navigates from there down + // to the member named `modelViewProjection` in that buffer. + // + // Once we have formed a cursor that "points" at the + // model-view projection matrix, we can set its data directly. + // + rootCursor["Uniforms"]["modelViewProjection"].setData( + deviceInfo.identityProjectionMatrix, + sizeof(float) * 16); + // + // Some readers might be concerned about the performance o + // the above operations because of the use of strings. For + // those readers, here are two things to note: + // + // * While these `operator[]` steps do need to perform string + // comparisons, they do *not* make copies of the strings or + // perform any heap allocation. + // + // * There are other overloads of `operator[]` that use the + // *index* of a parameter/field instead of its name, and those + // operations have fixed/constant overhead and perform no + // string comparisons. The indices used are independent of + // the target platform and graphics API, and can thus be + // hard-coded even in cross-platform code. + // + + // We also need to set up a few pieces of fixed-function pipeline + // state that are not bound by the pipeline state above. + // + renderEncoder->setVertexBuffer(0, gVertexBuffer); + renderEncoder->setPrimitiveTopology(PrimitiveTopology::TriangleList); + + // Finally, we are ready to issue a draw call for a single triangle. + // + renderEncoder->draw(3); + renderEncoder->endEncoding(); + commandBuffer->close(); + gQueue->executeCommandBuffer(commandBuffer); + + if (!isTestMode()) + { + // With that, we are done drawing for one frame, and ready for the next. + // + gSwapchain->present(); + } + } }; // This macro instantiates an appropriate main function to diff --git a/extras/formatting.sh b/extras/formatting.sh index 58d7d3509..664eb68b9 100755 --- a/extras/formatting.sh +++ b/extras/formatting.sh @@ -124,7 +124,6 @@ cpp_formatting() { } cmake_formatting -# Disable until we've formatted the code -# cpp_formatting +cpp_formatting exit $exit_code diff --git a/include/slang-com-helper.h b/include/slang-com-helper.h index fc8b7de58..557b278df 100644 --- a/include/slang-com-helper.h +++ b/include/slang-com-helper.h @@ -2,36 +2,90 @@ #define SLANG_COM_HELPER_H /** \file slang-com-helper.h -*/ + */ #include "slang.h" + #include /* !!!!!!!!!!!!!!!!!!!!! Macros to help checking SlangResult !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ -/*! Set SLANG_HANDLE_RESULT_FAIL(x) to code to be executed whenever an error occurs, and is detected by one of the macros */ +/*! Set SLANG_HANDLE_RESULT_FAIL(x) to code to be executed whenever an error occurs, and is detected + * by one of the macros */ #ifndef SLANG_HANDLE_RESULT_FAIL -# define SLANG_HANDLE_RESULT_FAIL(x) + #define SLANG_HANDLE_RESULT_FAIL(x) #endif -//! Helper macro, that makes it easy to add result checking to calls in functions/methods that themselves return Result. -#define SLANG_RETURN_ON_FAIL(x) { SlangResult _res = (x); if (SLANG_FAILED(_res)) { SLANG_HANDLE_RESULT_FAIL(_res); return _res; } } -//! Helper macro that can be used to test the return value from a call, and will return in a void method/function -#define SLANG_RETURN_VOID_ON_FAIL(x) { SlangResult _res = (x); if (SLANG_FAILED(_res)) { SLANG_HANDLE_RESULT_FAIL(_res); return; } } +//! Helper macro, that makes it easy to add result checking to calls in functions/methods that +//! themselves return Result. +#define SLANG_RETURN_ON_FAIL(x) \ + { \ + SlangResult _res = (x); \ + if (SLANG_FAILED(_res)) \ + { \ + SLANG_HANDLE_RESULT_FAIL(_res); \ + return _res; \ + } \ + } +//! Helper macro that can be used to test the return value from a call, and will return in a void +//! method/function +#define SLANG_RETURN_VOID_ON_FAIL(x) \ + { \ + SlangResult _res = (x); \ + if (SLANG_FAILED(_res)) \ + { \ + SLANG_HANDLE_RESULT_FAIL(_res); \ + return; \ + } \ + } //! Helper macro that will return false on failure. -#define SLANG_RETURN_FALSE_ON_FAIL(x) { SlangResult _res = (x); if (SLANG_FAILED(_res)) { SLANG_HANDLE_RESULT_FAIL(_res); return false; } } +#define SLANG_RETURN_FALSE_ON_FAIL(x) \ + { \ + SlangResult _res = (x); \ + if (SLANG_FAILED(_res)) \ + { \ + SLANG_HANDLE_RESULT_FAIL(_res); \ + return false; \ + } \ + } //! Helper macro that will return nullptr on failure. -#define SLANG_RETURN_NULL_ON_FAIL(x) { SlangResult _res = (x); if (SLANG_FAILED(_res)) { SLANG_HANDLE_RESULT_FAIL(_res); return nullptr; } } - -//! Helper macro that will assert if the return code from a call is failure, also returns the failure. -#define SLANG_ASSERT_ON_FAIL(x) { SlangResult _res = (x); if (SLANG_FAILED(_res)) { assert(false); return _res; } } -//! Helper macro that will assert if the result from a call is a failure, also returns. -#define SLANG_ASSERT_VOID_ON_FAIL(x) { SlangResult _res = (x); if (SLANG_FAILED(_res)) { assert(false); return; } } +#define SLANG_RETURN_NULL_ON_FAIL(x) \ + { \ + SlangResult _res = (x); \ + if (SLANG_FAILED(_res)) \ + { \ + SLANG_HANDLE_RESULT_FAIL(_res); \ + return nullptr; \ + } \ + } + +//! Helper macro that will assert if the return code from a call is failure, also returns the +//! failure. +#define SLANG_ASSERT_ON_FAIL(x) \ + { \ + SlangResult _res = (x); \ + if (SLANG_FAILED(_res)) \ + { \ + assert(false); \ + return _res; \ + } \ + } +//! Helper macro that will assert if the result from a call is a failure, also returns. +#define SLANG_ASSERT_VOID_ON_FAIL(x) \ + { \ + SlangResult _res = (x); \ + if (SLANG_FAILED(_res)) \ + { \ + assert(false); \ + return; \ + } \ + } /* !!!!!!!!!!!!!!!!!!!!!!! C++ helpers !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ #if defined(__cplusplus) -namespace Slang { +namespace Slang +{ // Alias SlangResult to Slang::Result typedef SlangResult Result; @@ -64,67 +118,79 @@ SLANG_FORCE_INLINE bool operator!=(const Slang::Guid& a, const Slang::Guid& b) return !(a == b); } -/* !!!!!!!! Macros to simplify implementing COM interfaces !!!!!!!!!!!!!!!!!!!!!!!!!!!! */ - -/* Assumes underlying implementation has a member m_refCount that is initialized to 0 and can have ++ and -- operate on it. -For SLANG_IUNKNOWN_QUERY_INTERFACE to work - must have a method 'getInterface' that returns valid pointers for the Guid, or nullptr -if not found. */ - -#define SLANG_IUNKNOWN_QUERY_INTERFACE \ -SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE \ -{ \ - ISlangUnknown* intf = getInterface(uuid); \ - if (intf) \ - { \ - addRef(); \ - *outObject = intf; \ - return SLANG_OK;\ - } \ - return SLANG_E_NO_INTERFACE;\ -} - -#define SLANG_IUNKNOWN_ADD_REF \ -SLANG_NO_THROW uint32_t SLANG_MCALL addRef() \ -{ \ - return ++m_refCount; \ -} - -#define SLANG_IUNKNOWN_RELEASE \ -SLANG_NO_THROW uint32_t SLANG_MCALL release() \ -{ \ - --m_refCount; \ - if (m_refCount == 0) \ - { \ - delete this; \ - return 0; \ - } \ - return m_refCount; \ -} - -#define SLANG_IUNKNOWN_ALL \ - SLANG_IUNKNOWN_QUERY_INTERFACE \ - SLANG_IUNKNOWN_ADD_REF \ - SLANG_IUNKNOWN_RELEASE - -// ------------------------ RefObject IUnknown ----------------------------- - -#define SLANG_REF_OBJECT_IUNKNOWN_QUERY_INTERFACE \ -SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE \ -{ \ - void* intf = getInterface(uuid); \ - if (intf) \ - { \ - addReference(); \ - *outObject = intf; \ - return SLANG_OK;\ - } \ - return SLANG_E_NO_INTERFACE;\ -} - -#define SLANG_REF_OBJECT_IUNKNOWN_ADD_REF SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return (uint32_t)addReference(); } -#define SLANG_REF_OBJECT_IUNKNOWN_RELEASE SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return (uint32_t)releaseReference(); } - -# define SLANG_REF_OBJECT_IUNKNOWN_ALL \ + /* !!!!!!!! Macros to simplify implementing COM interfaces !!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + + /* Assumes underlying implementation has a member m_refCount that is initialized to 0 and can + have ++ and -- operate on it. For SLANG_IUNKNOWN_QUERY_INTERFACE to work - must have a method + 'getInterface' that returns valid pointers for the Guid, or nullptr if not found. */ + + #define SLANG_IUNKNOWN_QUERY_INTERFACE \ + SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface( \ + SlangUUID const& uuid, \ + void** outObject) SLANG_OVERRIDE \ + { \ + ISlangUnknown* intf = getInterface(uuid); \ + if (intf) \ + { \ + addRef(); \ + *outObject = intf; \ + return SLANG_OK; \ + } \ + return SLANG_E_NO_INTERFACE; \ + } + + #define SLANG_IUNKNOWN_ADD_REF \ + SLANG_NO_THROW uint32_t SLANG_MCALL addRef() \ + { \ + return ++m_refCount; \ + } + + #define SLANG_IUNKNOWN_RELEASE \ + SLANG_NO_THROW uint32_t SLANG_MCALL release() \ + { \ + --m_refCount; \ + if (m_refCount == 0) \ + { \ + delete this; \ + return 0; \ + } \ + return m_refCount; \ + } + + #define SLANG_IUNKNOWN_ALL \ + SLANG_IUNKNOWN_QUERY_INTERFACE \ + SLANG_IUNKNOWN_ADD_REF \ + SLANG_IUNKNOWN_RELEASE + + // ------------------------ RefObject IUnknown ----------------------------- + + #define SLANG_REF_OBJECT_IUNKNOWN_QUERY_INTERFACE \ + SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface( \ + SlangUUID const& uuid, \ + void** outObject) SLANG_OVERRIDE \ + { \ + void* intf = getInterface(uuid); \ + if (intf) \ + { \ + addReference(); \ + *outObject = intf; \ + return SLANG_OK; \ + } \ + return SLANG_E_NO_INTERFACE; \ + } + + #define SLANG_REF_OBJECT_IUNKNOWN_ADD_REF \ + SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE \ + { \ + return (uint32_t)addReference(); \ + } + #define SLANG_REF_OBJECT_IUNKNOWN_RELEASE \ + SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE \ + { \ + return (uint32_t)releaseReference(); \ + } + + #define SLANG_REF_OBJECT_IUNKNOWN_ALL \ SLANG_REF_OBJECT_IUNKNOWN_QUERY_INTERFACE \ SLANG_REF_OBJECT_IUNKNOWN_ADD_REF \ SLANG_REF_OBJECT_IUNKNOWN_RELEASE diff --git a/include/slang-com-ptr.h b/include/slang-com-ptr.h index 00cc9dbb1..e9d211d92 100644 --- a/include/slang-com-ptr.h +++ b/include/slang-com-ptr.h @@ -6,20 +6,21 @@ #include #include -namespace Slang { +namespace Slang +{ /*! \brief ComPtr is a simple smart pointer that manages types which implement COM based interfaces. -\details A class that implements a COM, must derive from the IUnknown interface or a type that matches -it's layout exactly (such as ISlangUnknown). Trying to use this template with a class that doesn't follow -these rules, will lead to undefined behavior. -This is a 'strong' pointer type, and will AddRef when a non null pointer is set and Release when the pointer -leaves scope. -Using 'detach' allows a pointer to be removed from the management of the ComPtr. -To set the smart pointer to null, there is the method setNull, or alternatively just assign SLANG_NULL/nullptr. - -One edge case using the template is that sometimes you want access as a pointer to a pointer. Sometimes this -is to write into the smart pointer, other times to pass as an array. To handle these different behaviors -there are the methods readRef and writeRef, which are used instead of the & (ref) operator. For example +\details A class that implements a COM, must derive from the IUnknown interface or a type that +matches it's layout exactly (such as ISlangUnknown). Trying to use this template with a class that +doesn't follow these rules, will lead to undefined behavior. This is a 'strong' pointer type, and +will AddRef when a non null pointer is set and Release when the pointer leaves scope. Using 'detach' +allows a pointer to be removed from the management of the ComPtr. To set the smart pointer to null, +there is the method setNull, or alternatively just assign SLANG_NULL/nullptr. + +One edge case using the template is that sometimes you want access as a pointer to a pointer. +Sometimes this is to write into the smart pointer, other times to pass as an array. To handle these +different behaviors there are the methods readRef and writeRef, which are used instead of the & +(ref) operator. For example \code Void doSomething(ID3D12Resource** resources, IndexT numResources); @@ -44,115 +45,164 @@ enum InitAttach INIT_ATTACH }; -template +template class ComPtr { public: - typedef T Type; - typedef ComPtr ThisType; - typedef ISlangUnknown* Ptr; - - /// Constructors - /// Default Ctor. Sets to nullptr - SLANG_FORCE_INLINE ComPtr() :m_ptr(nullptr) {} - SLANG_FORCE_INLINE ComPtr(std::nullptr_t) : m_ptr(nullptr) {} - /// Sets, and ref counts. - SLANG_FORCE_INLINE explicit ComPtr(T* ptr) :m_ptr(ptr) { if (ptr) ((Ptr)ptr)->addRef(); } - /// The copy ctor - SLANG_FORCE_INLINE ComPtr(const ThisType& rhs) : m_ptr(rhs.m_ptr) { if (m_ptr) ((Ptr)m_ptr)->addRef(); } - - /// Ctor without adding to ref count. - SLANG_FORCE_INLINE explicit ComPtr(InitAttach, T* ptr) :m_ptr(ptr) { } - /// Ctor without adding to ref count - SLANG_FORCE_INLINE ComPtr(InitAttach, const ThisType& rhs) : m_ptr(rhs.m_ptr) { } + typedef T Type; + typedef ComPtr ThisType; + typedef ISlangUnknown* Ptr; + + /// Constructors + /// Default Ctor. Sets to nullptr + SLANG_FORCE_INLINE ComPtr() + : m_ptr(nullptr) + { + } + SLANG_FORCE_INLINE ComPtr(std::nullptr_t) + : m_ptr(nullptr) + { + } + /// Sets, and ref counts. + SLANG_FORCE_INLINE explicit ComPtr(T* ptr) + : m_ptr(ptr) + { + if (ptr) + ((Ptr)ptr)->addRef(); + } + /// The copy ctor + SLANG_FORCE_INLINE ComPtr(const ThisType& rhs) + : m_ptr(rhs.m_ptr) + { + if (m_ptr) + ((Ptr)m_ptr)->addRef(); + } + + /// Ctor without adding to ref count. + SLANG_FORCE_INLINE explicit ComPtr(InitAttach, T* ptr) + : m_ptr(ptr) + { + } + /// Ctor without adding to ref count + SLANG_FORCE_INLINE ComPtr(InitAttach, const ThisType& rhs) + : m_ptr(rhs.m_ptr) + { + } #ifdef SLANG_HAS_MOVE_SEMANTICS - /// Move Ctor - SLANG_FORCE_INLINE ComPtr(ThisType&& rhs) : m_ptr(rhs.m_ptr) { rhs.m_ptr = nullptr; } - /// Move assign - SLANG_FORCE_INLINE ComPtr& operator=(ThisType&& rhs) { T* swap = m_ptr; m_ptr = rhs.m_ptr; rhs.m_ptr = swap; return *this; } + /// Move Ctor + SLANG_FORCE_INLINE ComPtr(ThisType&& rhs) + : m_ptr(rhs.m_ptr) + { + rhs.m_ptr = nullptr; + } + /// Move assign + SLANG_FORCE_INLINE ComPtr& operator=(ThisType&& rhs) + { + T* swap = m_ptr; + m_ptr = rhs.m_ptr; + rhs.m_ptr = swap; + return *this; + } #endif - /// Destructor releases the pointer, assuming it is set - SLANG_FORCE_INLINE ~ComPtr() { if (m_ptr) ((Ptr)m_ptr)->release(); } - - // !!! Operators !!! - - /// Returns the dumb pointer - SLANG_FORCE_INLINE operator T *() const { return m_ptr; } - - SLANG_FORCE_INLINE T& operator*() { return *m_ptr; } - /// For making method invocations through the smart pointer work through the dumb pointer - SLANG_FORCE_INLINE T* operator->() const { return m_ptr; } - - /// Assign - SLANG_FORCE_INLINE const ThisType &operator=(const ThisType& rhs); - /// Assign from dumb ptr - SLANG_FORCE_INLINE T* operator=(T* in); - - /// Get the pointer and don't ref - SLANG_FORCE_INLINE T* get() const { return m_ptr; } - /// Release a contained nullptr pointer if set - SLANG_FORCE_INLINE void setNull(); - - /// Detach - SLANG_FORCE_INLINE T* detach() { T* ptr = m_ptr; m_ptr = nullptr; return ptr; } - /// Set to a pointer without changing the ref count - SLANG_FORCE_INLINE void attach(T* in) { m_ptr = in; } - - /// Get ready for writing (nulls contents) - SLANG_FORCE_INLINE T** writeRef() { setNull(); return &m_ptr; } - /// Get for read access - SLANG_FORCE_INLINE T*const* readRef() const { return &m_ptr; } - - /// Swap - void swap(ThisType& rhs); + /// Destructor releases the pointer, assuming it is set + SLANG_FORCE_INLINE ~ComPtr() + { + if (m_ptr) + ((Ptr)m_ptr)->release(); + } + + // !!! Operators !!! + + /// Returns the dumb pointer + SLANG_FORCE_INLINE operator T*() const { return m_ptr; } + + SLANG_FORCE_INLINE T& operator*() { return *m_ptr; } + /// For making method invocations through the smart pointer work through the dumb pointer + SLANG_FORCE_INLINE T* operator->() const { return m_ptr; } + + /// Assign + SLANG_FORCE_INLINE const ThisType& operator=(const ThisType& rhs); + /// Assign from dumb ptr + SLANG_FORCE_INLINE T* operator=(T* in); + + /// Get the pointer and don't ref + SLANG_FORCE_INLINE T* get() const { return m_ptr; } + /// Release a contained nullptr pointer if set + SLANG_FORCE_INLINE void setNull(); + + /// Detach + SLANG_FORCE_INLINE T* detach() + { + T* ptr = m_ptr; + m_ptr = nullptr; + return ptr; + } + /// Set to a pointer without changing the ref count + SLANG_FORCE_INLINE void attach(T* in) { m_ptr = in; } + + /// Get ready for writing (nulls contents) + SLANG_FORCE_INLINE T** writeRef() + { + setNull(); + return &m_ptr; + } + /// Get for read access + SLANG_FORCE_INLINE T* const* readRef() const { return &m_ptr; } + + /// Swap + void swap(ThisType& rhs); protected: - /// Gets the address of the dumb pointer. + /// Gets the address of the dumb pointer. // Disabled: use writeRef and readRef to get a reference based on usage. #ifndef SLANG_COM_PTR_ENABLE_REF_OPERATOR - SLANG_FORCE_INLINE T** operator&() = delete; + SLANG_FORCE_INLINE T** operator&() = delete; #endif - T* m_ptr; + T* m_ptr; }; //---------------------------------------------------------------------------- -template +template void ComPtr::setNull() { - if (m_ptr) - { - ((Ptr)m_ptr)->release(); - m_ptr = nullptr; - } + if (m_ptr) + { + ((Ptr)m_ptr)->release(); + m_ptr = nullptr; + } } //---------------------------------------------------------------------------- -template +template const ComPtr& ComPtr::operator=(const ThisType& rhs) { - if (rhs.m_ptr) ((Ptr)rhs.m_ptr)->addRef(); - if (m_ptr) ((Ptr)m_ptr)->release(); - m_ptr = rhs.m_ptr; - return *this; + if (rhs.m_ptr) + ((Ptr)rhs.m_ptr)->addRef(); + if (m_ptr) + ((Ptr)m_ptr)->release(); + m_ptr = rhs.m_ptr; + return *this; } //---------------------------------------------------------------------------- -template +template T* ComPtr::operator=(T* ptr) { - if (ptr) ((Ptr)ptr)->addRef(); - if (m_ptr) ((Ptr)m_ptr)->release(); - m_ptr = ptr; - return m_ptr; + if (ptr) + ((Ptr)ptr)->addRef(); + if (m_ptr) + ((Ptr)m_ptr)->release(); + m_ptr = ptr; + return m_ptr; } //---------------------------------------------------------------------------- -template +template void ComPtr::swap(ThisType& rhs) { - T* tmp = m_ptr; - m_ptr = rhs.m_ptr; - rhs.m_ptr = tmp; + T* tmp = m_ptr; + m_ptr = rhs.m_ptr; + rhs.m_ptr = tmp; } } // namespace Slang diff --git a/include/slang-deprecated.h b/include/slang-deprecated.h index 2cf4608b3..1c1350f9f 100644 --- a/include/slang-deprecated.h +++ b/include/slang-deprecated.h @@ -23,91 +23,75 @@ extern "C" /*! @brief Clean up after an instance of the Slang library. */ - SLANG_API void spDestroySession( - SlangSession* session); + SLANG_API void spDestroySession(SlangSession* session); /** @see slang::IGlobalSession::setSharedLibraryLoader - */ + */ SLANG_API void spSessionSetSharedLibraryLoader( - SlangSession* session, - ISlangSharedLibraryLoader* loader); + SlangSession* session, + ISlangSharedLibraryLoader* loader); /** @see slang::IGlobalSession::getSharedLibraryLoader - */ - SLANG_API ISlangSharedLibraryLoader* spSessionGetSharedLibraryLoader( - SlangSession* session); + */ + SLANG_API ISlangSharedLibraryLoader* spSessionGetSharedLibraryLoader(SlangSession* session); /** @see slang::IGlobalSession::checkCompileTargetSupport - */ - SLANG_API SlangResult spSessionCheckCompileTargetSupport( - SlangSession* session, - SlangCompileTarget target); + */ + SLANG_API SlangResult + spSessionCheckCompileTargetSupport(SlangSession* session, SlangCompileTarget target); /** @see slang::IGlobalSession::checkPassThroughSupport - */ - SLANG_API SlangResult spSessionCheckPassThroughSupport( - SlangSession* session, - SlangPassThrough passThrough - ); + */ + SLANG_API SlangResult + spSessionCheckPassThroughSupport(SlangSession* session, SlangPassThrough passThrough); /** @see slang::IGlobalSession::addBuiltins - */ + */ SLANG_API void spAddBuiltins( - SlangSession* session, - char const* sourcePath, - char const* sourceString); + SlangSession* session, + char const* sourcePath, + char const* sourceString); /* @see slang::IGlobalSession::createCompileRequest - */ - SLANG_API SlangCompileRequest* spCreateCompileRequest( - SlangSession* session); + */ + SLANG_API SlangCompileRequest* spCreateCompileRequest(SlangSession* session); /*! @brief Destroy a compile request. Note a request is a COM object and can be destroyed via 'Release'. */ - SLANG_API void spDestroyCompileRequest( - SlangCompileRequest* request); + SLANG_API void spDestroyCompileRequest(SlangCompileRequest* request); /*! @see slang::ICompileRequest::setFileSystem */ - SLANG_API void spSetFileSystem( - SlangCompileRequest* request, - ISlangFileSystem* fileSystem); + SLANG_API void spSetFileSystem(SlangCompileRequest* request, ISlangFileSystem* fileSystem); /*! @see slang::ICompileRequest::setCompileFlags */ - SLANG_API void spSetCompileFlags( - SlangCompileRequest* request, - SlangCompileFlags flags); + SLANG_API void spSetCompileFlags(SlangCompileRequest* request, SlangCompileFlags flags); /*! @see slang::ICompileRequest::getCompileFlags */ - SLANG_API SlangCompileFlags spGetCompileFlags( - SlangCompileRequest* request); + SLANG_API SlangCompileFlags spGetCompileFlags(SlangCompileRequest* request); /*! @see slang::ICompileRequest::setDumpIntermediates */ - SLANG_API void spSetDumpIntermediates( - SlangCompileRequest* request, - int enable); + SLANG_API void spSetDumpIntermediates(SlangCompileRequest* request, int enable); /*! @see slang::ICompileRequest::setDumpIntermediatePrefix */ - SLANG_API void spSetDumpIntermediatePrefix( - SlangCompileRequest* request, - const char* prefix); + SLANG_API void spSetDumpIntermediatePrefix(SlangCompileRequest* request, const char* prefix); /*! DEPRECATED: use `spSetTargetLineDirectiveMode` instead. @see slang::ICompileRequest::setLineDirectiveMode */ SLANG_API void spSetLineDirectiveMode( - SlangCompileRequest* request, - SlangLineDirectiveMode mode); - + SlangCompileRequest* request, + SlangLineDirectiveMode mode); + /*! @see slang::ICompileRequest::setTargetLineDirectiveMode */ SLANG_API void spSetTargetLineDirectiveMode( - SlangCompileRequest* request, + SlangCompileRequest* request, int targetIndex, - SlangLineDirectiveMode mode); + SlangLineDirectiveMode mode); /*! @see slang::ICompileRequest::setTargetLineDirectiveMode */ SLANG_API void spSetTargetForceGLSLScalarBufferLayout( - SlangCompileRequest* request, + SlangCompileRequest* request, int targetIndex, bool forceScalarLayout); @@ -118,296 +102,254 @@ extern "C" bool val); /*! @see slang::ICompileRequest::setIngoreCapabilityCheck */ - SLANG_API void spSetIgnoreCapabilityCheck( - slang::ICompileRequest* request, - bool val); + SLANG_API void spSetIgnoreCapabilityCheck(slang::ICompileRequest* request, bool val); /*! @see slang::ICompileRequest::setCodeGenTarget */ - SLANG_API void spSetCodeGenTarget( - SlangCompileRequest* request, - SlangCompileTarget target); + SLANG_API void spSetCodeGenTarget(SlangCompileRequest* request, SlangCompileTarget target); /*! @see slang::ICompileRequest::addCodeGenTarget */ - SLANG_API int spAddCodeGenTarget( - SlangCompileRequest* request, - SlangCompileTarget target); + SLANG_API int spAddCodeGenTarget(SlangCompileRequest* request, SlangCompileTarget target); /*! @see slang::ICompileRequest::setTargetProfile */ SLANG_API void spSetTargetProfile( - SlangCompileRequest* request, - int targetIndex, - SlangProfileID profile); + SlangCompileRequest* request, + int targetIndex, + SlangProfileID profile); /*! @see slang::ICompileRequest::setTargetFlags */ SLANG_API void spSetTargetFlags( - SlangCompileRequest* request, - int targetIndex, - SlangTargetFlags flags); - + SlangCompileRequest* request, + int targetIndex, + SlangTargetFlags flags); /*! @see slang::ICompileRequest::setTargetFloatingPointMode */ SLANG_API void spSetTargetFloatingPointMode( - SlangCompileRequest* request, - int targetIndex, - SlangFloatingPointMode mode); + SlangCompileRequest* request, + int targetIndex, + SlangFloatingPointMode mode); /*! @see slang::ICompileRequest::addTargetCapability */ SLANG_API void spAddTargetCapability( slang::ICompileRequest* request, - int targetIndex, - SlangCapabilityID capability); + int targetIndex, + SlangCapabilityID capability); /* DEPRECATED: use `spSetMatrixLayoutMode` instead. */ SLANG_API void spSetTargetMatrixLayoutMode( - SlangCompileRequest* request, - int targetIndex, - SlangMatrixLayoutMode mode); + SlangCompileRequest* request, + int targetIndex, + SlangMatrixLayoutMode mode); /*! @see slang::ICompileRequest::setMatrixLayoutMode */ - SLANG_API void spSetMatrixLayoutMode( - SlangCompileRequest* request, - SlangMatrixLayoutMode mode); + SLANG_API void spSetMatrixLayoutMode(SlangCompileRequest* request, SlangMatrixLayoutMode mode); /*! @see slang::ICompileRequest::setDebugInfoLevel */ - SLANG_API void spSetDebugInfoLevel( - SlangCompileRequest* request, - SlangDebugInfoLevel level); + SLANG_API void spSetDebugInfoLevel(SlangCompileRequest* request, SlangDebugInfoLevel level); /*! @see slang::ICompileRequest::setDebugInfoFormat */ - SLANG_API void spSetDebugInfoFormat( - SlangCompileRequest* request, - SlangDebugInfoFormat format); + SLANG_API void spSetDebugInfoFormat(SlangCompileRequest* request, SlangDebugInfoFormat format); /*! @see slang::ICompileRequest::setOptimizationLevel */ SLANG_API void spSetOptimizationLevel( - SlangCompileRequest* request, - SlangOptimizationLevel level); + SlangCompileRequest* request, + SlangOptimizationLevel level); - /*! @see slang::ICompileRequest::setOutputContainerFormat */ SLANG_API void spSetOutputContainerFormat( - SlangCompileRequest* request, - SlangContainerFormat format); + SlangCompileRequest* request, + SlangContainerFormat format); /*! @see slang::ICompileRequest::setPassThrough */ - SLANG_API void spSetPassThrough( - SlangCompileRequest* request, - SlangPassThrough passThrough); + SLANG_API void spSetPassThrough(SlangCompileRequest* request, SlangPassThrough passThrough); - /*! @see slang::ICompileRequest::setDiagnosticCallback */ + /*! @see slang::ICompileRequest::setDiagnosticCallback */ SLANG_API void spSetDiagnosticCallback( - SlangCompileRequest* request, + SlangCompileRequest* request, SlangDiagnosticCallback callback, - void const* userData); + void const* userData); /*! @see slang::ICompileRequest::setWriter */ SLANG_API void spSetWriter( - SlangCompileRequest* request, - SlangWriterChannel channel, - ISlangWriter* writer); + SlangCompileRequest* request, + SlangWriterChannel channel, + ISlangWriter* writer); /*! @see slang::ICompileRequest::getWriter */ - SLANG_API ISlangWriter* spGetWriter( - SlangCompileRequest* request, - SlangWriterChannel channel); + SLANG_API ISlangWriter* spGetWriter(SlangCompileRequest* request, SlangWriterChannel channel); /*! @see slang::ICompileRequest::addSearchPath */ - SLANG_API void spAddSearchPath( - SlangCompileRequest* request, - const char* searchDir); + SLANG_API void spAddSearchPath(SlangCompileRequest* request, const char* searchDir); - /*! @see slang::ICompileRequest::addPreprocessorDefine */ + /*! @see slang::ICompileRequest::addPreprocessorDefine */ SLANG_API void spAddPreprocessorDefine( - SlangCompileRequest* request, - const char* key, - const char* value); + SlangCompileRequest* request, + const char* key, + const char* value); /*! @see slang::ICompileRequest::processCommandLineArguments */ SLANG_API SlangResult spProcessCommandLineArguments( - SlangCompileRequest* request, - char const* const* args, - int argCount); + SlangCompileRequest* request, + char const* const* args, + int argCount); /*! @see slang::ICompileRequest::addTranslationUnit */ SLANG_API int spAddTranslationUnit( - SlangCompileRequest* request, - SlangSourceLanguage language, - char const* name); + SlangCompileRequest* request, + SlangSourceLanguage language, + char const* name); + - /*! @see slang::ICompileRequest::setDefaultModuleName */ SLANG_API void spSetDefaultModuleName( - SlangCompileRequest* request, + SlangCompileRequest* request, const char* defaultModuleName); /*! @see slang::ICompileRequest::addPreprocessorDefine */ SLANG_API void spTranslationUnit_addPreprocessorDefine( - SlangCompileRequest* request, - int translationUnitIndex, - const char* key, - const char* value); + SlangCompileRequest* request, + int translationUnitIndex, + const char* key, + const char* value); /*! @see slang::ICompileRequest::addTranslationUnitSourceFile */ SLANG_API void spAddTranslationUnitSourceFile( - SlangCompileRequest* request, - int translationUnitIndex, - char const* path); + SlangCompileRequest* request, + int translationUnitIndex, + char const* path); /*! @see slang::ICompileRequest::addTranslationUnitSourceString */ SLANG_API void spAddTranslationUnitSourceString( - SlangCompileRequest* request, - int translationUnitIndex, - char const* path, - char const* source); + SlangCompileRequest* request, + int translationUnitIndex, + char const* path, + char const* source); /*! @see slang::ICompileRequest::addLibraryReference */ SLANG_API SlangResult spAddLibraryReference( - SlangCompileRequest* request, + SlangCompileRequest* request, const char* basePath, const void* libData, size_t libDataSize); /*! @see slang::ICompileRequest::addTranslationUnitSourceStringSpan */ SLANG_API void spAddTranslationUnitSourceStringSpan( - SlangCompileRequest* request, - int translationUnitIndex, - char const* path, - char const* sourceBegin, - char const* sourceEnd); + SlangCompileRequest* request, + int translationUnitIndex, + char const* path, + char const* sourceBegin, + char const* sourceEnd); /*! @see slang::ICompileRequest::addTranslationUnitSourceBlob */ SLANG_API void spAddTranslationUnitSourceBlob( - SlangCompileRequest* request, - int translationUnitIndex, - char const* path, - ISlangBlob* sourceBlob); + SlangCompileRequest* request, + int translationUnitIndex, + char const* path, + ISlangBlob* sourceBlob); /*! @see slang::IGlobalSession::findProfile */ - SLANG_API SlangProfileID spFindProfile( - SlangSession* session, - char const* name); + SLANG_API SlangProfileID spFindProfile(SlangSession* session, char const* name); /*! @see slang::IGlobalSession::findCapability */ - SLANG_API SlangCapabilityID spFindCapability( - SlangSession* session, - char const* name); + SLANG_API SlangCapabilityID spFindCapability(SlangSession* session, char const* name); /*! @see slang::ICompileRequest::addEntryPoint */ SLANG_API int spAddEntryPoint( - SlangCompileRequest* request, - int translationUnitIndex, - char const* name, - SlangStage stage); + SlangCompileRequest* request, + int translationUnitIndex, + char const* name, + SlangStage stage); /*! @see slang::ICompileRequest::addEntryPointEx */ SLANG_API int spAddEntryPointEx( - SlangCompileRequest* request, - int translationUnitIndex, - char const* name, - SlangStage stage, - int genericArgCount, - char const** genericArgs); + SlangCompileRequest* request, + int translationUnitIndex, + char const* name, + SlangStage stage, + int genericArgCount, + char const** genericArgs); /*! @see slang::ICompileRequest::setGlobalGenericArgs */ SLANG_API SlangResult spSetGlobalGenericArgs( - SlangCompileRequest* request, - int genericArgCount, - char const** genericArgs); + SlangCompileRequest* request, + int genericArgCount, + char const** genericArgs); /*! @see slang::ICompileRequest::setTypeNameForGlobalExistentialTypeParam */ SLANG_API SlangResult spSetTypeNameForGlobalExistentialTypeParam( - SlangCompileRequest* request, - int slotIndex, - char const* typeName); + SlangCompileRequest* request, + int slotIndex, + char const* typeName); /*! @see slang::ICompileRequest::setTypeNameForEntryPointExistentialTypeParam */ SLANG_API SlangResult spSetTypeNameForEntryPointExistentialTypeParam( - SlangCompileRequest* request, - int entryPointIndex, - int slotIndex, - char const* typeName); + SlangCompileRequest* request, + int entryPointIndex, + int slotIndex, + char const* typeName); /*! @see slang::ICompileRequest::compile */ - SLANG_API SlangResult spCompile( - SlangCompileRequest* request); + SLANG_API SlangResult spCompile(SlangCompileRequest* request); /*! @see slang::ICompileRequest::getDiagnosticOutput */ - SLANG_API char const* spGetDiagnosticOutput( - SlangCompileRequest* request); + SLANG_API char const* spGetDiagnosticOutput(SlangCompileRequest* request); /*! @see slang::ICompileRequest::getDiagnosticOutputBlob */ - SLANG_API SlangResult spGetDiagnosticOutputBlob( - SlangCompileRequest* request, - ISlangBlob** outBlob); + SLANG_API SlangResult + spGetDiagnosticOutputBlob(SlangCompileRequest* request, ISlangBlob** outBlob); /*! @see slang::ICompileRequest::getDependencyFileCount */ - SLANG_API int - spGetDependencyFileCount( - SlangCompileRequest* request); + SLANG_API int spGetDependencyFileCount(SlangCompileRequest* request); /*! @see slang::ICompileRequest::getDependencyFilePath */ - SLANG_API char const* - spGetDependencyFilePath( - SlangCompileRequest* request, - int index); + SLANG_API char const* spGetDependencyFilePath(SlangCompileRequest* request, int index); /*! @see slang::ICompileRequest::getTranslationUnitCount */ - SLANG_API int - spGetTranslationUnitCount( - SlangCompileRequest* request); + SLANG_API int spGetTranslationUnitCount(SlangCompileRequest* request); /*! @see slang::ICompileRequest::getEntryPointSource */ - SLANG_API char const* spGetEntryPointSource( - SlangCompileRequest* request, - int entryPointIndex); + SLANG_API char const* spGetEntryPointSource(SlangCompileRequest* request, int entryPointIndex); /*! @see slang::ICompileRequest::getEntryPointCode */ SLANG_API void const* spGetEntryPointCode( - SlangCompileRequest* request, - int entryPointIndex, - size_t* outSize); + SlangCompileRequest* request, + int entryPointIndex, + size_t* outSize); /*! @see slang::ICompileRequest::getEntryPointCodeBlob */ SLANG_API SlangResult spGetEntryPointCodeBlob( - SlangCompileRequest* request, - int entryPointIndex, - int targetIndex, - ISlangBlob** outBlob); + SlangCompileRequest* request, + int entryPointIndex, + int targetIndex, + ISlangBlob** outBlob); /*! @see slang::ICompileRequest::getEntryPointHostCallable */ SLANG_API SlangResult spGetEntryPointHostCallable( - SlangCompileRequest* request, - int entryPointIndex, - int targetIndex, - ISlangSharedLibrary** outSharedLibrary); + SlangCompileRequest* request, + int entryPointIndex, + int targetIndex, + ISlangSharedLibrary** outSharedLibrary); /*! @see slang::ICompileRequest::getTargetCodeBlob */ - SLANG_API SlangResult spGetTargetCodeBlob( - SlangCompileRequest* request, - int targetIndex, - ISlangBlob** outBlob); + SLANG_API SlangResult + spGetTargetCodeBlob(SlangCompileRequest* request, int targetIndex, ISlangBlob** outBlob); /*! @see slang::ICompileRequest::getTargetHostCallable */ SLANG_API SlangResult spGetTargetHostCallable( - SlangCompileRequest* request, - int targetIndex, - ISlangSharedLibrary** outSharedLibrary); + SlangCompileRequest* request, + int targetIndex, + ISlangSharedLibrary** outSharedLibrary); /*! @see slang::ICompileRequest::getCompileRequestCode */ - SLANG_API void const* spGetCompileRequestCode( - SlangCompileRequest* request, - size_t* outSize); + SLANG_API void const* spGetCompileRequestCode(SlangCompileRequest* request, size_t* outSize); /*! @see slang::ICompileRequest::getContainerCode */ - SLANG_API SlangResult spGetContainerCode( - SlangCompileRequest* request, - ISlangBlob** outBlob); + SLANG_API SlangResult spGetContainerCode(SlangCompileRequest* request, ISlangBlob** outBlob); /*! @see slang::ICompileRequest::loadRepro */ SLANG_API SlangResult spLoadRepro( @@ -417,14 +359,10 @@ extern "C" size_t size); /*! @see slang::ICompileRequest::saveRepro */ - SLANG_API SlangResult spSaveRepro( - SlangCompileRequest* request, - ISlangBlob** outBlob - ); + SLANG_API SlangResult spSaveRepro(SlangCompileRequest* request, ISlangBlob** outBlob); /*! @see slang::ICompileRequest::enableReproCapture */ - SLANG_API SlangResult spEnableReproCapture( - SlangCompileRequest* request); + SLANG_API SlangResult spEnableReproCapture(SlangCompileRequest* request); /*! @see slang::ICompileRequest::getCompileTimeProfile */ SLANG_API SlangResult spGetCompileTimeProfile( @@ -435,8 +373,8 @@ extern "C" /** Extract contents of a repro. - Writes the contained files and manifest with their 'unique' names into fileSystem. For more details read the - docs/repro.md documentation. + Writes the contained files and manifest with their 'unique' names into fileSystem. For more + details read the docs/repro.md documentation. @param session The slang session @param reproData Holds the repro data @@ -452,13 +390,14 @@ extern "C" /* Turns a repro into a file system. - Makes the contents of the repro available as a file system - that is able to access the files with the same - paths as were used on the original repro file system. + Makes the contents of the repro available as a file system - that is able to access the files + with the same paths as were used on the original repro file system. @param session The slang session @param reproData The repro data @param reproDataSize The size of the repro data - @param replaceFileSystem Will attempt to load by unique names from this file system before using contents of the repro. Optional. + @param replaceFileSystem Will attempt to load by unique names from this file system before + using contents of the repro. Optional. @param outFileSystem The file system that can be used to access contents @returns A `SlangResult` to indicate success or failure. */ @@ -483,43 +422,63 @@ extern "C" // get reflection data from a compilation request - SLANG_API SlangReflection* spGetReflection( - SlangCompileRequest* request); + SLANG_API SlangReflection* spGetReflection(SlangCompileRequest* request); // User Attribute SLANG_API char const* spReflectionUserAttribute_GetName(SlangReflectionUserAttribute* attrib); - SLANG_API unsigned int spReflectionUserAttribute_GetArgumentCount(SlangReflectionUserAttribute* attrib); - SLANG_API SlangReflectionType* spReflectionUserAttribute_GetArgumentType(SlangReflectionUserAttribute* attrib, unsigned int index); - SLANG_API SlangResult spReflectionUserAttribute_GetArgumentValueInt(SlangReflectionUserAttribute* attrib, unsigned int index, int * rs); - SLANG_API SlangResult spReflectionUserAttribute_GetArgumentValueFloat(SlangReflectionUserAttribute* attrib, unsigned int index, float * rs); + SLANG_API unsigned int spReflectionUserAttribute_GetArgumentCount( + SlangReflectionUserAttribute* attrib); + SLANG_API SlangReflectionType* spReflectionUserAttribute_GetArgumentType( + SlangReflectionUserAttribute* attrib, + unsigned int index); + SLANG_API SlangResult spReflectionUserAttribute_GetArgumentValueInt( + SlangReflectionUserAttribute* attrib, + unsigned int index, + int* rs); + SLANG_API SlangResult spReflectionUserAttribute_GetArgumentValueFloat( + SlangReflectionUserAttribute* attrib, + unsigned int index, + float* rs); /** Returns the string-typed value of a user attribute argument - The string returned is not null-terminated. The length of the string is returned via `outSize`. - If index of out of range, or if the specified argument is not a string, the function will return nullptr. + The string returned is not null-terminated. The length of the string is returned via + `outSize`. If index of out of range, or if the specified argument is not a string, the + function will return nullptr. */ - SLANG_API const char* spReflectionUserAttribute_GetArgumentValueString(SlangReflectionUserAttribute* attrib, unsigned int index, size_t * outSize); + SLANG_API const char* spReflectionUserAttribute_GetArgumentValueString( + SlangReflectionUserAttribute* attrib, + unsigned int index, + size_t* outSize); // Type Reflection SLANG_API SlangTypeKind spReflectionType_GetKind(SlangReflectionType* type); SLANG_API unsigned int spReflectionType_GetUserAttributeCount(SlangReflectionType* type); - SLANG_API SlangReflectionUserAttribute* spReflectionType_GetUserAttribute(SlangReflectionType* type, unsigned int index); - SLANG_API SlangReflectionUserAttribute* spReflectionType_FindUserAttributeByName(SlangReflectionType* type, char const* name); - SLANG_API SlangReflectionType* spReflectionType_applySpecializations(SlangReflectionType* type, SlangReflectionGeneric* generic); + SLANG_API SlangReflectionUserAttribute* spReflectionType_GetUserAttribute( + SlangReflectionType* type, + unsigned int index); + SLANG_API SlangReflectionUserAttribute* spReflectionType_FindUserAttributeByName( + SlangReflectionType* type, + char const* name); + SLANG_API SlangReflectionType* spReflectionType_applySpecializations( + SlangReflectionType* type, + SlangReflectionGeneric* generic); SLANG_API unsigned int spReflectionType_GetFieldCount(SlangReflectionType* type); - SLANG_API SlangReflectionVariable* spReflectionType_GetFieldByIndex(SlangReflectionType* type, unsigned index); + SLANG_API SlangReflectionVariable* spReflectionType_GetFieldByIndex( + SlangReflectionType* type, + unsigned index); - /** Returns the number of elements in the given type. + /** Returns the number of elements in the given type. - This operation is valid for vector and array types. For other types it returns zero. + This operation is valid for vector and array types. For other types it returns zero. - When invoked on an unbounded-size array it will return `SLANG_UNBOUNDED_SIZE`, - which is defined to be `~size_t(0)`. + When invoked on an unbounded-size array it will return `SLANG_UNBOUNDED_SIZE`, + which is defined to be `~size_t(0)`. - If the size of a type cannot be statically computed, perhaps because it depends on - a generic parameter that has not been bound to a specific value, this function returns zero. - */ + If the size of a type cannot be statically computed, perhaps because it depends on + a generic parameter that has not been bound to a specific value, this function returns zero. + */ SLANG_API size_t spReflectionType_GetElementCount(SlangReflectionType* type); SLANG_API SlangReflectionType* spReflectionType_GetElementType(SlangReflectionType* type); @@ -530,73 +489,146 @@ extern "C" SLANG_API SlangResourceShape spReflectionType_GetResourceShape(SlangReflectionType* type); SLANG_API SlangResourceAccess spReflectionType_GetResourceAccess(SlangReflectionType* type); - SLANG_API SlangReflectionType* spReflectionType_GetResourceResultType(SlangReflectionType* type); + SLANG_API SlangReflectionType* spReflectionType_GetResourceResultType( + SlangReflectionType* type); SLANG_API char const* spReflectionType_GetName(SlangReflectionType* type); - SLANG_API SlangResult spReflectionType_GetFullName(SlangReflectionType* type, ISlangBlob** outNameBlob); - SLANG_API SlangReflectionGeneric* spReflectionType_GetGenericContainer(SlangReflectionType* type); + SLANG_API SlangResult + spReflectionType_GetFullName(SlangReflectionType* type, ISlangBlob** outNameBlob); + SLANG_API SlangReflectionGeneric* spReflectionType_GetGenericContainer( + SlangReflectionType* type); // Type Layout Reflection SLANG_API SlangReflectionType* spReflectionTypeLayout_GetType(SlangReflectionTypeLayout* type); SLANG_API SlangTypeKind spReflectionTypeLayout_getKind(SlangReflectionTypeLayout* type); - SLANG_API size_t spReflectionTypeLayout_GetSize(SlangReflectionTypeLayout* type, SlangParameterCategory category); - SLANG_API size_t spReflectionTypeLayout_GetStride(SlangReflectionTypeLayout* type, SlangParameterCategory category); - SLANG_API int32_t spReflectionTypeLayout_getAlignment(SlangReflectionTypeLayout* type, SlangParameterCategory category); + SLANG_API size_t spReflectionTypeLayout_GetSize( + SlangReflectionTypeLayout* type, + SlangParameterCategory category); + SLANG_API size_t spReflectionTypeLayout_GetStride( + SlangReflectionTypeLayout* type, + SlangParameterCategory category); + SLANG_API int32_t spReflectionTypeLayout_getAlignment( + SlangReflectionTypeLayout* type, + SlangParameterCategory category); SLANG_API uint32_t spReflectionTypeLayout_GetFieldCount(SlangReflectionTypeLayout* type); - SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_GetFieldByIndex(SlangReflectionTypeLayout* type, unsigned index); - - SLANG_API SlangInt spReflectionTypeLayout_findFieldIndexByName(SlangReflectionTypeLayout* typeLayout, const char* nameBegin, const char* nameEnd); - - SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_GetExplicitCounter(SlangReflectionTypeLayout* typeLayout); - - SLANG_API size_t spReflectionTypeLayout_GetElementStride(SlangReflectionTypeLayout* type, SlangParameterCategory category); - SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_GetElementTypeLayout(SlangReflectionTypeLayout* type); - SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_GetElementVarLayout(SlangReflectionTypeLayout* type); - SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_getContainerVarLayout(SlangReflectionTypeLayout* type); - - SLANG_API SlangParameterCategory spReflectionTypeLayout_GetParameterCategory(SlangReflectionTypeLayout* type); + SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_GetFieldByIndex( + SlangReflectionTypeLayout* type, + unsigned index); + + SLANG_API SlangInt spReflectionTypeLayout_findFieldIndexByName( + SlangReflectionTypeLayout* typeLayout, + const char* nameBegin, + const char* nameEnd); + + SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_GetExplicitCounter( + SlangReflectionTypeLayout* typeLayout); + + SLANG_API size_t spReflectionTypeLayout_GetElementStride( + SlangReflectionTypeLayout* type, + SlangParameterCategory category); + SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_GetElementTypeLayout( + SlangReflectionTypeLayout* type); + SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_GetElementVarLayout( + SlangReflectionTypeLayout* type); + SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_getContainerVarLayout( + SlangReflectionTypeLayout* type); + + SLANG_API SlangParameterCategory + spReflectionTypeLayout_GetParameterCategory(SlangReflectionTypeLayout* type); SLANG_API unsigned spReflectionTypeLayout_GetCategoryCount(SlangReflectionTypeLayout* type); - SLANG_API SlangParameterCategory spReflectionTypeLayout_GetCategoryByIndex(SlangReflectionTypeLayout* type, unsigned index); + SLANG_API SlangParameterCategory + spReflectionTypeLayout_GetCategoryByIndex(SlangReflectionTypeLayout* type, unsigned index); - SLANG_API SlangMatrixLayoutMode spReflectionTypeLayout_GetMatrixLayoutMode(SlangReflectionTypeLayout* type); + SLANG_API SlangMatrixLayoutMode + spReflectionTypeLayout_GetMatrixLayoutMode(SlangReflectionTypeLayout* type); SLANG_API int spReflectionTypeLayout_getGenericParamIndex(SlangReflectionTypeLayout* type); - SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_getPendingDataTypeLayout(SlangReflectionTypeLayout* type); + SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_getPendingDataTypeLayout( + SlangReflectionTypeLayout* type); - SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_getSpecializedTypePendingDataVarLayout(SlangReflectionTypeLayout* type); + SLANG_API SlangReflectionVariableLayout* + spReflectionTypeLayout_getSpecializedTypePendingDataVarLayout(SlangReflectionTypeLayout* type); SLANG_API SlangInt spReflectionType_getSpecializedTypeArgCount(SlangReflectionType* type); - SLANG_API SlangReflectionType* spReflectionType_getSpecializedTypeArgType(SlangReflectionType* type, SlangInt index); - - SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeCount(SlangReflectionTypeLayout* typeLayout); - SLANG_API SlangBindingType spReflectionTypeLayout_getBindingRangeType(SlangReflectionTypeLayout* typeLayout, SlangInt index); - SLANG_API SlangInt spReflectionTypeLayout_isBindingRangeSpecializable(SlangReflectionTypeLayout* typeLayout, SlangInt index); - SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeBindingCount(SlangReflectionTypeLayout* typeLayout, SlangInt index); - SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_getBindingRangeLeafTypeLayout(SlangReflectionTypeLayout* typeLayout, SlangInt index); - SLANG_API SlangReflectionVariable* spReflectionTypeLayout_getBindingRangeLeafVariable(SlangReflectionTypeLayout* typeLayout, SlangInt index); - SLANG_API SlangImageFormat spReflectionTypeLayout_getBindingRangeImageFormat(SlangReflectionTypeLayout* typeLayout, SlangInt index); - SLANG_API SlangInt spReflectionTypeLayout_getFieldBindingRangeOffset(SlangReflectionTypeLayout* typeLayout, SlangInt fieldIndex); - SLANG_API SlangInt spReflectionTypeLayout_getExplicitCounterBindingRangeOffset(SlangReflectionTypeLayout* inTypeLayout); - - SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeDescriptorSetIndex(SlangReflectionTypeLayout* typeLayout, SlangInt index); - SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeFirstDescriptorRangeIndex(SlangReflectionTypeLayout* typeLayout, SlangInt index); - SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeDescriptorRangeCount(SlangReflectionTypeLayout* typeLayout, SlangInt index); - - SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetCount(SlangReflectionTypeLayout* typeLayout); - SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetSpaceOffset(SlangReflectionTypeLayout* typeLayout, SlangInt setIndex); - SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetDescriptorRangeCount(SlangReflectionTypeLayout* typeLayout, SlangInt setIndex); - SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetDescriptorRangeIndexOffset(SlangReflectionTypeLayout* typeLayout, SlangInt setIndex, SlangInt rangeIndex); - SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetDescriptorRangeDescriptorCount(SlangReflectionTypeLayout* typeLayout, SlangInt setIndex, SlangInt rangeIndex); - SLANG_API SlangBindingType spReflectionTypeLayout_getDescriptorSetDescriptorRangeType(SlangReflectionTypeLayout* typeLayout, SlangInt setIndex, SlangInt rangeIndex); - SLANG_API SlangParameterCategory spReflectionTypeLayout_getDescriptorSetDescriptorRangeCategory(SlangReflectionTypeLayout* typeLayout, SlangInt setIndex, SlangInt rangeIndex); - - SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeCount(SlangReflectionTypeLayout* typeLayout); - SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeBindingRangeIndex(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex); - SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeSpaceOffset(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex); - SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_getSubObjectRangeOffset(SlangReflectionTypeLayout* typeLayout, SlangInt subObjectRangeIndex); + SLANG_API SlangReflectionType* spReflectionType_getSpecializedTypeArgType( + SlangReflectionType* type, + SlangInt index); + + SLANG_API SlangInt + spReflectionTypeLayout_getBindingRangeCount(SlangReflectionTypeLayout* typeLayout); + SLANG_API SlangBindingType spReflectionTypeLayout_getBindingRangeType( + SlangReflectionTypeLayout* typeLayout, + SlangInt index); + SLANG_API SlangInt spReflectionTypeLayout_isBindingRangeSpecializable( + SlangReflectionTypeLayout* typeLayout, + SlangInt index); + SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeBindingCount( + SlangReflectionTypeLayout* typeLayout, + SlangInt index); + SLANG_API SlangReflectionTypeLayout* spReflectionTypeLayout_getBindingRangeLeafTypeLayout( + SlangReflectionTypeLayout* typeLayout, + SlangInt index); + SLANG_API SlangReflectionVariable* spReflectionTypeLayout_getBindingRangeLeafVariable( + SlangReflectionTypeLayout* typeLayout, + SlangInt index); + SLANG_API SlangImageFormat spReflectionTypeLayout_getBindingRangeImageFormat( + SlangReflectionTypeLayout* typeLayout, + SlangInt index); + SLANG_API SlangInt spReflectionTypeLayout_getFieldBindingRangeOffset( + SlangReflectionTypeLayout* typeLayout, + SlangInt fieldIndex); + SLANG_API SlangInt spReflectionTypeLayout_getExplicitCounterBindingRangeOffset( + SlangReflectionTypeLayout* inTypeLayout); + + SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeDescriptorSetIndex( + SlangReflectionTypeLayout* typeLayout, + SlangInt index); + SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeFirstDescriptorRangeIndex( + SlangReflectionTypeLayout* typeLayout, + SlangInt index); + SLANG_API SlangInt spReflectionTypeLayout_getBindingRangeDescriptorRangeCount( + SlangReflectionTypeLayout* typeLayout, + SlangInt index); + + SLANG_API SlangInt + spReflectionTypeLayout_getDescriptorSetCount(SlangReflectionTypeLayout* typeLayout); + SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetSpaceOffset( + SlangReflectionTypeLayout* typeLayout, + SlangInt setIndex); + SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetDescriptorRangeCount( + SlangReflectionTypeLayout* typeLayout, + SlangInt setIndex); + SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetDescriptorRangeIndexOffset( + SlangReflectionTypeLayout* typeLayout, + SlangInt setIndex, + SlangInt rangeIndex); + SLANG_API SlangInt spReflectionTypeLayout_getDescriptorSetDescriptorRangeDescriptorCount( + SlangReflectionTypeLayout* typeLayout, + SlangInt setIndex, + SlangInt rangeIndex); + SLANG_API SlangBindingType spReflectionTypeLayout_getDescriptorSetDescriptorRangeType( + SlangReflectionTypeLayout* typeLayout, + SlangInt setIndex, + SlangInt rangeIndex); + SLANG_API SlangParameterCategory spReflectionTypeLayout_getDescriptorSetDescriptorRangeCategory( + SlangReflectionTypeLayout* typeLayout, + SlangInt setIndex, + SlangInt rangeIndex); + + SLANG_API SlangInt + spReflectionTypeLayout_getSubObjectRangeCount(SlangReflectionTypeLayout* typeLayout); + SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeBindingRangeIndex( + SlangReflectionTypeLayout* typeLayout, + SlangInt subObjectRangeIndex); + SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeSpaceOffset( + SlangReflectionTypeLayout* typeLayout, + SlangInt subObjectRangeIndex); + SLANG_API SlangReflectionVariableLayout* spReflectionTypeLayout_getSubObjectRangeOffset( + SlangReflectionTypeLayout* typeLayout, + SlangInt subObjectRangeIndex); #if 0 SLANG_API SlangInt spReflectionTypeLayout_getSubObjectRangeCount(SlangReflectionTypeLayout* typeLayout); @@ -615,49 +647,88 @@ extern "C" SLANG_API char const* spReflectionVariable_GetName(SlangReflectionVariable* var); SLANG_API SlangReflectionType* spReflectionVariable_GetType(SlangReflectionVariable* var); - SLANG_API SlangReflectionModifier* spReflectionVariable_FindModifier(SlangReflectionVariable* var, SlangModifierID modifierID); + SLANG_API SlangReflectionModifier* spReflectionVariable_FindModifier( + SlangReflectionVariable* var, + SlangModifierID modifierID); SLANG_API unsigned int spReflectionVariable_GetUserAttributeCount(SlangReflectionVariable* var); - SLANG_API SlangReflectionUserAttribute* spReflectionVariable_GetUserAttribute(SlangReflectionVariable* var, unsigned int index); - SLANG_API SlangReflectionUserAttribute* spReflectionVariable_FindUserAttributeByName(SlangReflectionVariable* var, SlangSession * globalSession, char const* name); + SLANG_API SlangReflectionUserAttribute* spReflectionVariable_GetUserAttribute( + SlangReflectionVariable* var, + unsigned int index); + SLANG_API SlangReflectionUserAttribute* spReflectionVariable_FindUserAttributeByName( + SlangReflectionVariable* var, + SlangSession* globalSession, + char const* name); SLANG_API bool spReflectionVariable_HasDefaultValue(SlangReflectionVariable* inVar); - SLANG_API SlangReflectionGeneric* spReflectionVariable_GetGenericContainer(SlangReflectionVariable* var); - SLANG_API SlangReflectionVariable* spReflectionVariable_applySpecializations(SlangReflectionVariable* var, SlangReflectionGeneric* generic); + SLANG_API SlangReflectionGeneric* spReflectionVariable_GetGenericContainer( + SlangReflectionVariable* var); + SLANG_API SlangReflectionVariable* spReflectionVariable_applySpecializations( + SlangReflectionVariable* var, + SlangReflectionGeneric* generic); // Variable Layout Reflection - SLANG_API SlangReflectionVariable* spReflectionVariableLayout_GetVariable(SlangReflectionVariableLayout* var); + SLANG_API SlangReflectionVariable* spReflectionVariableLayout_GetVariable( + SlangReflectionVariableLayout* var); - SLANG_API SlangReflectionTypeLayout* spReflectionVariableLayout_GetTypeLayout(SlangReflectionVariableLayout* var); + SLANG_API SlangReflectionTypeLayout* spReflectionVariableLayout_GetTypeLayout( + SlangReflectionVariableLayout* var); - SLANG_API size_t spReflectionVariableLayout_GetOffset(SlangReflectionVariableLayout* var, SlangParameterCategory category); - SLANG_API size_t spReflectionVariableLayout_GetSpace(SlangReflectionVariableLayout* var, SlangParameterCategory category); + SLANG_API size_t spReflectionVariableLayout_GetOffset( + SlangReflectionVariableLayout* var, + SlangParameterCategory category); + SLANG_API size_t spReflectionVariableLayout_GetSpace( + SlangReflectionVariableLayout* var, + SlangParameterCategory category); - SLANG_API char const* spReflectionVariableLayout_GetSemanticName(SlangReflectionVariableLayout* var); - SLANG_API size_t spReflectionVariableLayout_GetSemanticIndex(SlangReflectionVariableLayout* var); + SLANG_API char const* spReflectionVariableLayout_GetSemanticName( + SlangReflectionVariableLayout* var); + SLANG_API size_t + spReflectionVariableLayout_GetSemanticIndex(SlangReflectionVariableLayout* var); // Function Reflection SLANG_API SlangReflectionDecl* spReflectionFunction_asDecl(SlangReflectionFunction* func); SLANG_API char const* spReflectionFunction_GetName(SlangReflectionFunction* func); - SLANG_API SlangReflectionModifier* spReflectionFunction_FindModifier(SlangReflectionFunction* var, SlangModifierID modifierID); - SLANG_API unsigned int spReflectionFunction_GetUserAttributeCount(SlangReflectionFunction* func); - SLANG_API SlangReflectionUserAttribute* spReflectionFunction_GetUserAttribute(SlangReflectionFunction* func, unsigned int index); - SLANG_API SlangReflectionUserAttribute* spReflectionFunction_FindUserAttributeByName(SlangReflectionFunction* func, SlangSession* globalSession, char const* name); + SLANG_API SlangReflectionModifier* spReflectionFunction_FindModifier( + SlangReflectionFunction* var, + SlangModifierID modifierID); + SLANG_API unsigned int spReflectionFunction_GetUserAttributeCount( + SlangReflectionFunction* func); + SLANG_API SlangReflectionUserAttribute* spReflectionFunction_GetUserAttribute( + SlangReflectionFunction* func, + unsigned int index); + SLANG_API SlangReflectionUserAttribute* spReflectionFunction_FindUserAttributeByName( + SlangReflectionFunction* func, + SlangSession* globalSession, + char const* name); SLANG_API unsigned int spReflectionFunction_GetParameterCount(SlangReflectionFunction* func); - SLANG_API SlangReflectionVariable* spReflectionFunction_GetParameter(SlangReflectionFunction* func, unsigned index); - SLANG_API SlangReflectionType* spReflectionFunction_GetResultType(SlangReflectionFunction* func); - SLANG_API SlangReflectionGeneric* spReflectionFunction_GetGenericContainer(SlangReflectionFunction* func); - SLANG_API SlangReflectionFunction* spReflectionFunction_applySpecializations(SlangReflectionFunction* func, SlangReflectionGeneric* generic); - SLANG_API SlangReflectionFunction* spReflectionFunction_specializeWithArgTypes(SlangReflectionFunction* func, SlangInt argTypeCount, SlangReflectionType* const* argTypes); + SLANG_API SlangReflectionVariable* spReflectionFunction_GetParameter( + SlangReflectionFunction* func, + unsigned index); + SLANG_API SlangReflectionType* spReflectionFunction_GetResultType( + SlangReflectionFunction* func); + SLANG_API SlangReflectionGeneric* spReflectionFunction_GetGenericContainer( + SlangReflectionFunction* func); + SLANG_API SlangReflectionFunction* spReflectionFunction_applySpecializations( + SlangReflectionFunction* func, + SlangReflectionGeneric* generic); + SLANG_API SlangReflectionFunction* spReflectionFunction_specializeWithArgTypes( + SlangReflectionFunction* func, + SlangInt argTypeCount, + SlangReflectionType* const* argTypes); SLANG_API bool spReflectionFunction_isOverloaded(SlangReflectionFunction* func); SLANG_API unsigned int spReflectionFunction_getOverloadCount(SlangReflectionFunction* func); - SLANG_API SlangReflectionFunction* spReflectionFunction_getOverload(SlangReflectionFunction* func, unsigned int index); + SLANG_API SlangReflectionFunction* spReflectionFunction_getOverload( + SlangReflectionFunction* func, + unsigned int index); // Abstract Decl Reflection SLANG_API unsigned int spReflectionDecl_getChildrenCount(SlangReflectionDecl* parentDecl); - SLANG_API SlangReflectionDecl* spReflectionDecl_getChild(SlangReflectionDecl* parentDecl, unsigned int index); + SLANG_API SlangReflectionDecl* spReflectionDecl_getChild( + SlangReflectionDecl* parentDecl, + unsigned int index); SLANG_API char const* spReflectionDecl_getName(SlangReflectionDecl* decl); SLANG_API SlangDeclKind spReflectionDecl_getKind(SlangReflectionDecl* decl); SLANG_API SlangReflectionFunction* spReflectionDecl_castToFunction(SlangReflectionDecl* decl); @@ -670,18 +741,37 @@ extern "C" SLANG_API SlangReflectionDecl* spReflectionGeneric_asDecl(SlangReflectionGeneric* generic); SLANG_API char const* spReflectionGeneric_GetName(SlangReflectionGeneric* generic); - SLANG_API unsigned int spReflectionGeneric_GetTypeParameterCount(SlangReflectionGeneric* generic); - SLANG_API SlangReflectionVariable* spReflectionGeneric_GetTypeParameter(SlangReflectionGeneric* generic, unsigned index); - SLANG_API unsigned int spReflectionGeneric_GetValueParameterCount(SlangReflectionGeneric* generic); - SLANG_API SlangReflectionVariable* spReflectionGeneric_GetValueParameter(SlangReflectionGeneric* generic, unsigned index); - SLANG_API unsigned int spReflectionGeneric_GetTypeParameterConstraintCount(SlangReflectionGeneric* generic, SlangReflectionVariable* typeParam); - SLANG_API SlangReflectionType* spReflectionGeneric_GetTypeParameterConstraintType(SlangReflectionGeneric* generic, SlangReflectionVariable* typeParam, unsigned index); + SLANG_API unsigned int spReflectionGeneric_GetTypeParameterCount( + SlangReflectionGeneric* generic); + SLANG_API SlangReflectionVariable* spReflectionGeneric_GetTypeParameter( + SlangReflectionGeneric* generic, + unsigned index); + SLANG_API unsigned int spReflectionGeneric_GetValueParameterCount( + SlangReflectionGeneric* generic); + SLANG_API SlangReflectionVariable* spReflectionGeneric_GetValueParameter( + SlangReflectionGeneric* generic, + unsigned index); + SLANG_API unsigned int spReflectionGeneric_GetTypeParameterConstraintCount( + SlangReflectionGeneric* generic, + SlangReflectionVariable* typeParam); + SLANG_API SlangReflectionType* spReflectionGeneric_GetTypeParameterConstraintType( + SlangReflectionGeneric* generic, + SlangReflectionVariable* typeParam, + unsigned index); SLANG_API SlangDeclKind spReflectionGeneric_GetInnerKind(SlangReflectionGeneric* generic); - SLANG_API SlangReflectionDecl* spReflectionGeneric_GetInnerDecl(SlangReflectionGeneric* generic); - SLANG_API SlangReflectionGeneric* spReflectionGeneric_GetOuterGenericContainer(SlangReflectionGeneric* generic); - SLANG_API SlangReflectionType* spReflectionGeneric_GetConcreteType(SlangReflectionGeneric* generic, SlangReflectionVariable* typeParam); - SLANG_API int64_t spReflectionGeneric_GetConcreteIntVal(SlangReflectionGeneric* generic, SlangReflectionVariable* valueParam); - SLANG_API SlangReflectionGeneric* spReflectionGeneric_applySpecializations(SlangReflectionGeneric* currGeneric, SlangReflectionGeneric* generic); + SLANG_API SlangReflectionDecl* spReflectionGeneric_GetInnerDecl( + SlangReflectionGeneric* generic); + SLANG_API SlangReflectionGeneric* spReflectionGeneric_GetOuterGenericContainer( + SlangReflectionGeneric* generic); + SLANG_API SlangReflectionType* spReflectionGeneric_GetConcreteType( + SlangReflectionGeneric* generic, + SlangReflectionVariable* typeParam); + SLANG_API int64_t spReflectionGeneric_GetConcreteIntVal( + SlangReflectionGeneric* generic, + SlangReflectionVariable* valueParam); + SLANG_API SlangReflectionGeneric* spReflectionGeneric_applySpecializations( + SlangReflectionGeneric* currGeneric, + SlangReflectionGeneric* generic); /** Get the stage that a variable belongs to (if any). @@ -691,11 +781,11 @@ extern "C" point *or* at the global scope of a stage-specific GLSL code file (e.g., an `in` parameter in a GLSL `.vs` file belongs to the vertex stage). */ - SLANG_API SlangStage spReflectionVariableLayout_getStage( - SlangReflectionVariableLayout* var); + SLANG_API SlangStage spReflectionVariableLayout_getStage(SlangReflectionVariableLayout* var); - SLANG_API SlangReflectionVariableLayout* spReflectionVariableLayout_getPendingDataLayout(SlangReflectionVariableLayout* var); + SLANG_API SlangReflectionVariableLayout* spReflectionVariableLayout_getPendingDataLayout( + SlangReflectionVariableLayout* var); // Shader Parameter Reflection @@ -707,14 +797,13 @@ extern "C" SlangInt entryPointIndex, SlangInt targetIndex, SlangParameterCategory category, // is this a `t` register? `s` register? - SlangUInt spaceIndex, // `space` for D3D12, `set` for Vulkan - SlangUInt registerIndex, // `register` for D3D12, `binding` for Vulkan + SlangUInt spaceIndex, // `space` for D3D12, `set` for Vulkan + SlangUInt registerIndex, // `register` for D3D12, `binding` for Vulkan bool& outUsed); // Entry Point Reflection - SLANG_API char const* spReflectionEntryPoint_getName( - SlangReflectionEntryPoint* entryPoint); + SLANG_API char const* spReflectionEntryPoint_getName(SlangReflectionEntryPoint* entryPoint); SLANG_API char const* spReflectionEntryPoint_getNameOverride( SlangReflectionEntryPoint* entryPoint); @@ -726,15 +815,15 @@ extern "C" SlangReflectionEntryPoint* entryPoint); SLANG_API SlangReflectionVariableLayout* spReflectionEntryPoint_getParameterByIndex( - SlangReflectionEntryPoint* entryPoint, - unsigned index); + SlangReflectionEntryPoint* entryPoint, + unsigned index); SLANG_API SlangStage spReflectionEntryPoint_getStage(SlangReflectionEntryPoint* entryPoint); SLANG_API void spReflectionEntryPoint_getComputeThreadGroupSize( - SlangReflectionEntryPoint* entryPoint, - SlangUInt axisCount, - SlangUInt* outSizeAlongAxis); + SlangReflectionEntryPoint* entryPoint, + SlangUInt axisCount, + SlangUInt* outSizeAlongAxis); SLANG_API void spReflectionEntryPoint_getComputeWaveSize( SlangReflectionEntryPoint* entryPoint, @@ -753,80 +842,106 @@ extern "C" SlangReflectionEntryPoint* entryPoint); // SlangReflectionTypeParameter - SLANG_API char const* spReflectionTypeParameter_GetName(SlangReflectionTypeParameter* typeParam); + SLANG_API char const* spReflectionTypeParameter_GetName( + SlangReflectionTypeParameter* typeParam); SLANG_API unsigned spReflectionTypeParameter_GetIndex(SlangReflectionTypeParameter* typeParam); - SLANG_API unsigned spReflectionTypeParameter_GetConstraintCount(SlangReflectionTypeParameter* typeParam); - SLANG_API SlangReflectionType* spReflectionTypeParameter_GetConstraintByIndex(SlangReflectionTypeParameter* typeParam, unsigned int index); + SLANG_API unsigned spReflectionTypeParameter_GetConstraintCount( + SlangReflectionTypeParameter* typeParam); + SLANG_API SlangReflectionType* spReflectionTypeParameter_GetConstraintByIndex( + SlangReflectionTypeParameter* typeParam, + unsigned int index); // Shader Reflection SLANG_API unsigned spReflection_GetParameterCount(SlangReflection* reflection); - SLANG_API SlangReflectionParameter* spReflection_GetParameterByIndex(SlangReflection* reflection, unsigned index); + SLANG_API SlangReflectionParameter* spReflection_GetParameterByIndex( + SlangReflection* reflection, + unsigned index); SLANG_API unsigned int spReflection_GetTypeParameterCount(SlangReflection* reflection); - SLANG_API SlangReflectionTypeParameter* spReflection_GetTypeParameterByIndex(SlangReflection* reflection, unsigned int index); - SLANG_API SlangReflectionTypeParameter* spReflection_FindTypeParameter(SlangReflection* reflection, char const* name); - - SLANG_API SlangReflectionType* spReflection_FindTypeByName(SlangReflection* reflection, char const* name); - SLANG_API SlangReflectionTypeLayout* spReflection_GetTypeLayout(SlangReflection* reflection, SlangReflectionType* reflectionType, SlangLayoutRules rules); - - SLANG_API SlangReflectionFunction* spReflection_FindFunctionByName(SlangReflection* reflection, char const* name); - SLANG_API SlangReflectionFunction* spReflection_FindFunctionByNameInType(SlangReflection* reflection, SlangReflectionType* reflType, char const* name); - SLANG_API SlangReflectionVariable* spReflection_FindVarByNameInType(SlangReflection* reflection, SlangReflectionType* reflType, char const* name); + SLANG_API SlangReflectionTypeParameter* spReflection_GetTypeParameterByIndex( + SlangReflection* reflection, + unsigned int index); + SLANG_API SlangReflectionTypeParameter* spReflection_FindTypeParameter( + SlangReflection* reflection, + char const* name); + + SLANG_API SlangReflectionType* spReflection_FindTypeByName( + SlangReflection* reflection, + char const* name); + SLANG_API SlangReflectionTypeLayout* spReflection_GetTypeLayout( + SlangReflection* reflection, + SlangReflectionType* reflectionType, + SlangLayoutRules rules); + + SLANG_API SlangReflectionFunction* spReflection_FindFunctionByName( + SlangReflection* reflection, + char const* name); + SLANG_API SlangReflectionFunction* spReflection_FindFunctionByNameInType( + SlangReflection* reflection, + SlangReflectionType* reflType, + char const* name); + SLANG_API SlangReflectionVariable* spReflection_FindVarByNameInType( + SlangReflection* reflection, + SlangReflectionType* reflType, + char const* name); SLANG_API SlangUInt spReflection_getEntryPointCount(SlangReflection* reflection); - SLANG_API SlangReflectionEntryPoint* spReflection_getEntryPointByIndex(SlangReflection* reflection, SlangUInt index); - SLANG_API SlangReflectionEntryPoint* spReflection_findEntryPointByName(SlangReflection* reflection, char const* name); + SLANG_API SlangReflectionEntryPoint* spReflection_getEntryPointByIndex( + SlangReflection* reflection, + SlangUInt index); + SLANG_API SlangReflectionEntryPoint* spReflection_findEntryPointByName( + SlangReflection* reflection, + char const* name); SLANG_API SlangUInt spReflection_getGlobalConstantBufferBinding(SlangReflection* reflection); SLANG_API size_t spReflection_getGlobalConstantBufferSize(SlangReflection* reflection); SLANG_API SlangReflectionType* spReflection_specializeType( - SlangReflection* reflection, - SlangReflectionType* type, - SlangInt specializationArgCount, + SlangReflection* reflection, + SlangReflectionType* type, + SlangInt specializationArgCount, SlangReflectionType* const* specializationArgs, - ISlangBlob** outDiagnostics); - + ISlangBlob** outDiagnostics); + SLANG_API SlangReflectionGeneric* spReflection_specializeGeneric( - SlangReflection* inProgramLayout, - SlangReflectionGeneric* generic, - SlangInt argCount, - SlangReflectionGenericArgType const* argTypes, - SlangReflectionGenericArg const* args, - ISlangBlob** outDiagnostics); - + SlangReflection* inProgramLayout, + SlangReflectionGeneric* generic, + SlangInt argCount, + SlangReflectionGenericArgType const* argTypes, + SlangReflectionGenericArg const* args, + ISlangBlob** outDiagnostics); + SLANG_API bool spReflection_isSubType( - SlangReflection * reflection, + SlangReflection* reflection, SlangReflectionType* subType, SlangReflectionType* superType); - /// Get the number of hashed strings - SLANG_API SlangUInt spReflection_getHashedStringCount( - SlangReflection* reflection); + /// Get the number of hashed strings + SLANG_API SlangUInt spReflection_getHashedStringCount(SlangReflection* reflection); - /// Get a hashed string. The number of chars is written in outCount. - /// The count does *NOT* including terminating 0. The returned string will be 0 terminated. + /// Get a hashed string. The number of chars is written in outCount. + /// The count does *NOT* including terminating 0. The returned string will be 0 terminated. SLANG_API const char* spReflection_getHashedString( - SlangReflection* reflection, + SlangReflection* reflection, SlangUInt index, size_t* outCount); - /// Compute a string hash. - /// Count should *NOT* include terminating zero. + /// Compute a string hash. + /// Count should *NOT* include terminating zero. SLANG_API SlangUInt32 spComputeStringHash(const char* chars, size_t count); - /// Get a type layout representing reflection information for the global-scope prameters. + /// Get a type layout representing reflection information for the global-scope prameters. SLANG_API SlangReflectionTypeLayout* spReflection_getGlobalParamsTypeLayout( SlangReflection* reflection); - /// Get a variable layout representing reflection information for the global-scope prameters. + /// Get a variable layout representing reflection information for the global-scope prameters. SLANG_API SlangReflectionVariableLayout* spReflection_getGlobalParamsVarLayout( SlangReflection* reflection); SLANG_API char const* spGetTranslationUnitSource( - SlangCompileRequest* request, - int translationUnitIndex); + SlangCompileRequest* request, + int translationUnitIndex); #ifdef __cplusplus } #endif @@ -836,678 +951,643 @@ SLANG_API slang::ISession* spReflection_GetSession(SlangReflection* reflection); namespace slang { - struct IComponentType; - struct IModule; -} +struct IComponentType; +struct IModule; +} // namespace slang extern "C" { /** @see slang::ICompileRequest::getProgram - */ - SLANG_API SlangResult spCompileRequest_getProgram( - SlangCompileRequest* request, - slang::IComponentType** outProgram); + */ + SLANG_API SlangResult + spCompileRequest_getProgram(SlangCompileRequest* request, slang::IComponentType** outProgram); /** @see slang::ICompileRequest::getProgramWithEntryPoints - */ + */ SLANG_API SlangResult spCompileRequest_getProgramWithEntryPoints( - SlangCompileRequest* request, + SlangCompileRequest* request, slang::IComponentType** outProgram); /** @see slang::ICompileRequest::getEntryPoint - */ + */ SLANG_API SlangResult spCompileRequest_getEntryPoint( - SlangCompileRequest* request, - SlangInt entryPointIndex, + SlangCompileRequest* request, + SlangInt entryPointIndex, slang::IComponentType** outEntryPoint); /** @see slang::ICompileRequest::getModule - */ + */ SLANG_API SlangResult spCompileRequest_getModule( - SlangCompileRequest* request, - SlangInt translationUnitIndex, - slang::IModule** outModule); + SlangCompileRequest* request, + SlangInt translationUnitIndex, + slang::IModule** outModule); /** @see slang::ICompileRequest::getSession - */ - SLANG_API SlangResult spCompileRequest_getSession( - SlangCompileRequest* request, - slang::ISession** outSession); + */ + SLANG_API SlangResult + spCompileRequest_getSession(SlangCompileRequest* request, slang::ISession** outSession); } namespace slang { +/*! +@brief A request for one or more compilation actions to be performed. +*/ +struct ICompileRequest : public ISlangUnknown +{ + SLANG_COM_INTERFACE( + 0x96d33993, + 0x317c, + 0x4db5, + {0xaf, 0xd8, 0x66, 0x6e, 0xe7, 0x72, 0x48, 0xe2}) + + /** Set the filesystem hook to use for a compile request + + The provided `fileSystem` will be used to load any files that + need to be loaded during processing of the compile `request`. + This includes: + + - Source files loaded via `spAddTranslationUnitSourceFile` + - Files referenced via `#include` + - Files loaded to resolve `#import` operations + */ + virtual SLANG_NO_THROW void SLANG_MCALL setFileSystem(ISlangFileSystem* fileSystem) = 0; + + /*! + @brief Set flags to be used for compilation. + */ + virtual SLANG_NO_THROW void SLANG_MCALL setCompileFlags(SlangCompileFlags flags) = 0; + + /*! + @brief Returns the compilation flags previously set with `setCompileFlags` + */ + virtual SLANG_NO_THROW SlangCompileFlags SLANG_MCALL getCompileFlags() = 0; + /*! - @brief A request for one or more compilation actions to be performed. + @brief Set whether to dump intermediate results (for debugging) or not. */ - struct ICompileRequest : public ISlangUnknown - { - SLANG_COM_INTERFACE( 0x96d33993, 0x317c, 0x4db5, { 0xaf, 0xd8, 0x66, 0x6e, 0xe7, 0x72, 0x48, 0xe2 } ) - - /** Set the filesystem hook to use for a compile request - - The provided `fileSystem` will be used to load any files that - need to be loaded during processing of the compile `request`. - This includes: - - - Source files loaded via `spAddTranslationUnitSourceFile` - - Files referenced via `#include` - - Files loaded to resolve `#import` operations - */ - virtual SLANG_NO_THROW void SLANG_MCALL setFileSystem( - ISlangFileSystem* fileSystem) = 0; - - /*! - @brief Set flags to be used for compilation. - */ - virtual SLANG_NO_THROW void SLANG_MCALL setCompileFlags( - SlangCompileFlags flags) = 0; - - /*! - @brief Returns the compilation flags previously set with `setCompileFlags` - */ - virtual SLANG_NO_THROW SlangCompileFlags SLANG_MCALL getCompileFlags() = 0; - - /*! - @brief Set whether to dump intermediate results (for debugging) or not. - */ - virtual SLANG_NO_THROW void SLANG_MCALL setDumpIntermediates( - int enable) = 0; - - virtual SLANG_NO_THROW void SLANG_MCALL setDumpIntermediatePrefix( - const char* prefix) = 0; - - /*! - @brief Set whether (and how) `#line` directives should be output. - */ - virtual SLANG_NO_THROW void SLANG_MCALL setLineDirectiveMode( - SlangLineDirectiveMode mode) = 0; - - /*! - @brief Sets the target for code generation. - @param target The code generation target. Possible values are: - - SLANG_GLSL. Generates GLSL code. - - SLANG_HLSL. Generates HLSL code. - - SLANG_SPIRV. Generates SPIR-V code. - */ - virtual SLANG_NO_THROW void SLANG_MCALL setCodeGenTarget( - SlangCompileTarget target) = 0; - - /*! - @brief Add a code-generation target to be used. - */ - virtual SLANG_NO_THROW int SLANG_MCALL addCodeGenTarget( - SlangCompileTarget target) = 0; - - virtual SLANG_NO_THROW void SLANG_MCALL setTargetProfile( - int targetIndex, - SlangProfileID profile) = 0; - - virtual SLANG_NO_THROW void SLANG_MCALL setTargetFlags( - int targetIndex, - SlangTargetFlags flags) = 0; - - /*! - @brief Set the floating point mode (e.g., precise or fast) to use a target. - */ - virtual SLANG_NO_THROW void SLANG_MCALL setTargetFloatingPointMode( - int targetIndex, - SlangFloatingPointMode mode) = 0; - - /* DEPRECATED: use `spSetMatrixLayoutMode` instead. */ - virtual SLANG_NO_THROW void SLANG_MCALL setTargetMatrixLayoutMode( - int targetIndex, - SlangMatrixLayoutMode mode) = 0; - - virtual SLANG_NO_THROW void SLANG_MCALL setMatrixLayoutMode( - SlangMatrixLayoutMode mode) = 0; - - /*! - @brief Set the level of debug information to produce. - */ - virtual SLANG_NO_THROW void SLANG_MCALL setDebugInfoLevel( - SlangDebugInfoLevel level) = 0; - - /*! - @brief Set the level of optimization to perform. - */ - virtual SLANG_NO_THROW void SLANG_MCALL setOptimizationLevel( - SlangOptimizationLevel level) = 0; - - - - /*! - @brief Set the container format to be used for binary output. - */ - virtual SLANG_NO_THROW void SLANG_MCALL setOutputContainerFormat( - SlangContainerFormat format) = 0; - - virtual SLANG_NO_THROW void SLANG_MCALL setPassThrough( - SlangPassThrough passThrough) = 0; - - - virtual SLANG_NO_THROW void SLANG_MCALL setDiagnosticCallback( - SlangDiagnosticCallback callback, - void const* userData) = 0; - - virtual SLANG_NO_THROW void SLANG_MCALL setWriter( - SlangWriterChannel channel, - ISlangWriter* writer) = 0; - - virtual SLANG_NO_THROW ISlangWriter* SLANG_MCALL getWriter( - SlangWriterChannel channel) = 0; - - /*! - @brief Add a path to use when searching for referenced files. - This will be used for both `#include` directives and also for explicit `__import` declarations. - @param ctx The compilation context. - @param searchDir The additional search directory. - */ - virtual SLANG_NO_THROW void SLANG_MCALL addSearchPath( - const char* searchDir) = 0; - - /*! - @brief Add a macro definition to be used during preprocessing. - @param key The name of the macro to define. - @param value The value of the macro to define. - */ - virtual SLANG_NO_THROW void SLANG_MCALL addPreprocessorDefine( - const char* key, - const char* value) = 0; - - /*! - @brief Set options using arguments as if specified via command line. - @return Returns SlangResult. On success SLANG_SUCCEEDED(result) is true. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL processCommandLineArguments( - char const* const* args, - int argCount) = 0; - - /** Add a distinct translation unit to the compilation request - - `name` is optional. - Returns the zero-based index of the translation unit created. - */ - virtual SLANG_NO_THROW int SLANG_MCALL addTranslationUnit( - SlangSourceLanguage language, - char const* name) = 0; - - - /** Set a default module name. Translation units will default to this module name if one is not - passed. If not set each translation unit will get a unique name. - */ - virtual SLANG_NO_THROW void SLANG_MCALL setDefaultModuleName( - const char* defaultModuleName) = 0; - - /** Add a preprocessor definition that is scoped to a single translation unit. - - @param translationUnitIndex The index of the translation unit to get the definition. - @param key The name of the macro to define. - @param value The value of the macro to define. - */ - virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitPreprocessorDefine( - int translationUnitIndex, - const char* key, - const char* value) = 0; - - - /** Add a source file to the given translation unit. - - If a user-defined file system has been specified via - `spSetFileSystem`, then it will be used to load the - file at `path`. Otherwise, Slang will use the OS - file system. - - This function does *not* search for a file using - the registered search paths (`spAddSearchPath`), - and instead using the given `path` as-is. - */ - virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceFile( - int translationUnitIndex, - char const* path) = 0; - - /** Add a source string to the given translation unit. - - @param translationUnitIndex The index of the translation unit to add source to. - @param path The file-system path that should be assumed for the source code. - @param source A null-terminated UTF-8 encoded string of source code. - - The implementation will make a copy of the source code data. - An application may free the buffer immediately after this call returns. - - The `path` will be used in any diagnostic output, as well - as to determine the base path when resolving relative - `#include`s. - */ - virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceString( - int translationUnitIndex, - char const* path, - char const* source) = 0; - - - /** Add a slang library - such that its contents can be referenced during linking. - This is equivalent to the -r command line option. - - @param basePath The base path used to lookup referenced modules. - @param libData The library data - @param libDataSize The size of the library data - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL addLibraryReference( - const char* basePath, - const void* libData, - size_t libDataSize) = 0; - - /** Add a source string to the given translation unit. - - @param translationUnitIndex The index of the translation unit to add source to. - @param path The file-system path that should be assumed for the source code. - @param sourceBegin A pointer to a buffer of UTF-8 encoded source code. - @param sourceEnd A pointer to to the end of the buffer specified in `sourceBegin` - - The implementation will make a copy of the source code data. - An application may free the buffer immediately after this call returns. - - The `path` will be used in any diagnostic output, as well - as to determine the base path when resolving relative - `#include`s. - */ - virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceStringSpan( - int translationUnitIndex, - char const* path, - char const* sourceBegin, - char const* sourceEnd) = 0; - - /** Add a blob of source code to the given translation unit. - - @param translationUnitIndex The index of the translation unit to add source to. - @param path The file-system path that should be assumed for the source code. - @param sourceBlob A blob containing UTF-8 encoded source code. - @param sourceEnd A pointer to to the end of the buffer specified in `sourceBegin` - - The compile request will retain a reference to the blob. - - The `path` will be used in any diagnostic output, as well - as to determine the base path when resolving relative - `#include`s. - */ - virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceBlob( - int translationUnitIndex, - char const* path, - ISlangBlob* sourceBlob) = 0; - - /** Add an entry point in a particular translation unit - */ - virtual SLANG_NO_THROW int SLANG_MCALL addEntryPoint( - int translationUnitIndex, - char const* name, - SlangStage stage) = 0; - - /** Add an entry point in a particular translation unit, - with additional arguments that specify the concrete - type names for entry-point generic type parameters. - */ - virtual SLANG_NO_THROW int SLANG_MCALL addEntryPointEx( - int translationUnitIndex, - char const* name, - SlangStage stage, - int genericArgCount, - char const** genericArgs) = 0; - - /** Specify the arguments to use for global generic parameters. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL setGlobalGenericArgs( - int genericArgCount, - char const** genericArgs) = 0; - - /** Specify the concrete type to be used for a global "existential slot." - - Every shader parameter (or leaf field of a `struct`-type shader parameter) - that has an interface or array-of-interface type introduces an existential - slot. The number of slots consumed by a shader parameter, and the starting - slot of each parameter can be queried via the reflection API using - `SLANG_PARAMETER_CATEGORY_EXISTENTIAL_TYPE_PARAM`. - - In order to generate specialized code, a concrete type needs to be specified - for each existential slot. This function specifies the name of the type - (or in general a type *expression*) to use for a specific slot at the - global scope. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL setTypeNameForGlobalExistentialTypeParam( - int slotIndex, - char const* typeName) = 0; - - /** Specify the concrete type to be used for an entry-point "existential slot." - - Every shader parameter (or leaf field of a `struct`-type shader parameter) - that has an interface or array-of-interface type introduces an existential - slot. The number of slots consumed by a shader parameter, and the starting - slot of each parameter can be queried via the reflection API using - `SLANG_PARAMETER_CATEGORY_EXISTENTIAL_TYPE_PARAM`. - - In order to generate specialized code, a concrete type needs to be specified - for each existential slot. This function specifies the name of the type - (or in general a type *expression*) to use for a specific slot at the - entry-point scope. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL setTypeNameForEntryPointExistentialTypeParam( - int entryPointIndex, - int slotIndex, - char const* typeName) = 0; - - /** Enable or disable an experimental, best-effort GLSL frontend - */ - virtual SLANG_NO_THROW void SLANG_MCALL setAllowGLSLInput( - bool value) = 0; - - /** Execute the compilation request. - - @returns SlangResult, SLANG_OK on success. Use SLANG_SUCCEEDED() and SLANG_FAILED() to test SlangResult. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile() = 0; - - - /** Get any diagnostic messages reported by the compiler. - - @returns A null-terminated UTF-8 encoded string of diagnostic messages. - - The returned pointer is only guaranteed to be valid - until `request` is destroyed. Applications that wish to - hold on to the diagnostic output for longer should use - `getDiagnosticOutputBlob`. - */ - virtual SLANG_NO_THROW char const* SLANG_MCALL getDiagnosticOutput() = 0; - - /** Get diagnostic messages reported by the compiler. - - @param outBlob A pointer to receive a blob holding a nul-terminated UTF-8 encoded string of diagnostic messages. - @returns A `SlangResult` indicating success or failure. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getDiagnosticOutputBlob( - ISlangBlob** outBlob) = 0; - - - /** Get the number of files that this compilation depended on. - - This includes both the explicit source files, as well as any - additional files that were transitively referenced (e.g., via - a `#include` directive). - */ - virtual SLANG_NO_THROW int SLANG_MCALL getDependencyFileCount() = 0; - - /** Get the path to a file this compilation depended on. - */ - virtual SLANG_NO_THROW char const* SLANG_MCALL getDependencyFilePath( - int index) = 0; - - /** Get the number of translation units associated with the compilation request - */ - virtual SLANG_NO_THROW int SLANG_MCALL getTranslationUnitCount() = 0; - - /** Get the output source code associated with a specific entry point. - - The lifetime of the output pointer is the same as `request`. - */ - virtual SLANG_NO_THROW char const* SLANG_MCALL getEntryPointSource( - int entryPointIndex) = 0; - - /** Get the output bytecode associated with a specific entry point. - - The lifetime of the output pointer is the same as `request`. - */ - virtual SLANG_NO_THROW void const* SLANG_MCALL getEntryPointCode( - int entryPointIndex, - size_t* outSize) = 0; - - /** Get the output code associated with a specific entry point. - - @param entryPointIndex The index of the entry point to get code for. - @param targetIndex The index of the target to get code for (default: zero). - @param outBlob A pointer that will receive the blob of code - @returns A `SlangResult` to indicate success or failure. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointCodeBlob( - int entryPointIndex, - int targetIndex, - ISlangBlob** outBlob) = 0; - - /** Get entry point 'callable' functions accessible through the ISlangSharedLibrary interface. - - That the functions remain in scope as long as the ISlangSharedLibrary interface is in scope. - - NOTE! Requires a compilation target of SLANG_HOST_CALLABLE. - - @param entryPointIndex The index of the entry point to get code for. - @param targetIndex The index of the target to get code for (default: zero). - @param outSharedLibrary A pointer to a ISharedLibrary interface which functions can be queried on. - @returns A `SlangResult` to indicate success or failure. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointHostCallable( - int entryPointIndex, - int targetIndex, - ISlangSharedLibrary** outSharedLibrary) = 0; - - /** Get the output code associated with a specific target. - - @param targetIndex The index of the target to get code for (default: zero). - @param outBlob A pointer that will receive the blob of code - @returns A `SlangResult` to indicate success or failure. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTargetCodeBlob( - int targetIndex, - ISlangBlob** outBlob) = 0; - - /** Get 'callable' functions for a target accessible through the ISlangSharedLibrary interface. - - That the functions remain in scope as long as the ISlangSharedLibrary interface is in scope. - - NOTE! Requires a compilation target of SLANG_HOST_CALLABLE. - - @param targetIndex The index of the target to get code for (default: zero). - @param outSharedLibrary A pointer to a ISharedLibrary interface which functions can be queried on. - @returns A `SlangResult` to indicate success or failure. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTargetHostCallable( - int targetIndex, - ISlangSharedLibrary** outSharedLibrary) = 0; - - /** Get the output bytecode associated with an entire compile request. - - The lifetime of the output pointer is the same as `request` and the last spCompile. - - @param outSize The size of the containers contents in bytes. Will be zero if there is no code available. - @returns Pointer to start of the contained data, or nullptr if there is no code available. - */ - virtual SLANG_NO_THROW void const* SLANG_MCALL getCompileRequestCode( - size_t* outSize) = 0; - - /** Get the compilation result as a file system. - The result is not written to the actual OS file system, but is made avaiable as an - in memory representation. - */ - virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL getCompileRequestResultAsFileSystem() = 0; - - /** Return the container code as a blob. The container blob is created as part of a compilation (with spCompile), - and a container is produced with a suitable ContainerFormat. - - @param outSize The blob containing the container data. - @returns A `SlangResult` to indicate success or failure. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getContainerCode( - ISlangBlob** outBlob) = 0; - - /** Load repro from memory specified. - - Should only be performed on a newly created request. - - NOTE! When using the fileSystem, files will be loaded via their `unique names` as if they are part of the flat file system. This - mechanism is described more fully in docs/repro.md. - - @param fileSystem An (optional) filesystem. Pass nullptr to just use contents of repro held in data. - @param data The data to load from. - @param size The size of the data to load from. - @returns A `SlangResult` to indicate success or failure. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadRepro( - ISlangFileSystem* fileSystem, - const void* data, - size_t size) = 0; - - /** Save repro state. Should *typically* be performed after spCompile, so that everything - that is needed for a compilation is available. - - @param outBlob Blob that will hold the serialized state - @returns A `SlangResult` to indicate success or failure. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveRepro( - ISlangBlob** outBlob) = 0; - - /** Enable repro capture. - - Should be set after any ISlangFileSystem has been set, but before any compilation. It ensures that everything - that the ISlangFileSystem accesses will be correctly recorded. - Note that if a ISlangFileSystem/ISlangFileSystemExt isn't explicitly set (ie the default is used), then the - request will automatically be set up to record everything appropriate. - - @returns A `SlangResult` to indicate success or failure. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL enableReproCapture() = 0; - - /** Get the (linked) program for a compile request. - - The linked program will include all of the global-scope modules for the - translation units in the program, plus any modules that they `import` - (transitively), specialized to any global specialization arguments that - were provided via the API. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getProgram( - slang::IComponentType** outProgram) = 0; - - /** Get the (partially linked) component type for an entry point. - - The returned component type will include the entry point at the - given index, and will be specialized using any specialization arguments - that were provided for it via the API. - - The returned component will *not* include the modules representing - the global scope and its dependencies/specialization, so a client - program will typically want to compose this component type with - the one returned by `spCompileRequest_getProgram` to get a complete - and usable component type from which kernel code can be requested. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPoint( - SlangInt entryPointIndex, - slang::IComponentType** outEntryPoint) = 0; - - /** Get the (un-linked) module for a translation unit. - - The returned module will not be linked against any dependencies, - nor against any entry points (even entry points declared inside - the module). Similarly, the module will not be specialized - to the arguments that might have been provided via the API. - - This function provides an atomic unit of loaded code that - is suitable for looking up types and entry points in the - given module, and for linking together to produce a composite - program that matches the needs of an application. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getModule( - SlangInt translationUnitIndex, - slang::IModule** outModule) = 0; - - /** Get the `ISession` handle behind the `SlangCompileRequest`. - TODO(JS): Arguably this should just return the session pointer. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getSession( - slang::ISession** outSession) = 0; - - /** get reflection data from a compilation request */ - virtual SLANG_NO_THROW SlangReflection* SLANG_MCALL getReflection() = 0; - - /** Make output specially handled for command line output */ - virtual SLANG_NO_THROW void SLANG_MCALL setCommandLineCompilerMode() = 0; - - /** Add a defined capability that should be assumed available on the target */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL addTargetCapability( - SlangInt targetIndex, - SlangCapabilityID capability) = 0; - - /** Get the (linked) program for a compile request, including all entry points. - - The resulting program will include all of the global-scope modules for the - translation units in the program, plus any modules that they `import` - (transitively), specialized to any global specialization arguments that - were provided via the API, as well as all entry points specified for compilation, - specialized to their entry-point specialization arguments. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getProgramWithEntryPoints( - slang::IComponentType** outProgram) = 0; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL isParameterLocationUsed( - SlangInt entryPointIndex, - SlangInt targetIndex, - SlangParameterCategory category, - SlangUInt spaceIndex, - SlangUInt registerIndex, - bool& outUsed) = 0; - - /** Set the line directive mode for a target. - */ - virtual SLANG_NO_THROW void SLANG_MCALL setTargetLineDirectiveMode( - SlangInt targetIndex, - SlangLineDirectiveMode mode) = 0; - - /** Set whether to use scalar buffer layouts for GLSL/Vulkan targets. - If true, the generated GLSL/Vulkan code will use `scalar` layout for storage buffers. - If false, the resulting code will std430 for storage buffers. - */ - virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceGLSLScalarBufferLayout(int targetIndex, bool forceScalarLayout) = 0; - - /** Overrides the severity of a specific diagnostic message. - - @param messageID Numeric identifier of the message to override, - as defined in the 1st parameter of the DIAGNOSTIC macro. - @param overrideSeverity New severity of the message. If the message is originally Error or Fatal, - the new severity cannot be lower than that. - */ - virtual SLANG_NO_THROW void SLANG_MCALL overrideDiagnosticSeverity( - SlangInt messageID, - SlangSeverity overrideSeverity) = 0; - - /** Returns the currently active flags of the request's diagnostic sink. */ - virtual SLANG_NO_THROW SlangDiagnosticFlags SLANG_MCALL getDiagnosticFlags() = 0; - - /** Sets the flags of the request's diagnostic sink. - The previously specified flags are discarded. */ - virtual SLANG_NO_THROW void SLANG_MCALL setDiagnosticFlags(SlangDiagnosticFlags flags) = 0; - - /** Set the debug format to be used for debugging information */ - virtual SLANG_NO_THROW void SLANG_MCALL setDebugInfoFormat(SlangDebugInfoFormat debugFormat) = 0; - - virtual SLANG_NO_THROW void SLANG_MCALL setEnableEffectAnnotations(bool value) = 0; - - virtual SLANG_NO_THROW void SLANG_MCALL setReportDownstreamTime(bool value) = 0; - - virtual SLANG_NO_THROW void SLANG_MCALL setReportPerfBenchmark(bool value) = 0; - - virtual SLANG_NO_THROW void SLANG_MCALL setSkipSPIRVValidation(bool value) = 0; - - virtual SLANG_NO_THROW void SLANG_MCALL setTargetUseMinimumSlangOptimization(int targetIndex, bool value) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL setDumpIntermediates(int enable) = 0; - virtual SLANG_NO_THROW void SLANG_MCALL setIgnoreCapabilityCheck(bool value) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL setDumpIntermediatePrefix(const char* prefix) = 0; - // return a copy of internal profiling results, and if `shouldClear` is true, clear the internal profiling results before returning. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getCompileTimeProfile(ISlangProfiler** compileTimeProfile, bool shouldClear) = 0; + /*! + @brief Set whether (and how) `#line` directives should be output. + */ + virtual SLANG_NO_THROW void SLANG_MCALL setLineDirectiveMode(SlangLineDirectiveMode mode) = 0; + + /*! + @brief Sets the target for code generation. + @param target The code generation target. Possible values are: + - SLANG_GLSL. Generates GLSL code. + - SLANG_HLSL. Generates HLSL code. + - SLANG_SPIRV. Generates SPIR-V code. + */ + virtual SLANG_NO_THROW void SLANG_MCALL setCodeGenTarget(SlangCompileTarget target) = 0; + + /*! + @brief Add a code-generation target to be used. + */ + virtual SLANG_NO_THROW int SLANG_MCALL addCodeGenTarget(SlangCompileTarget target) = 0; - virtual SLANG_NO_THROW void SLANG_MCALL setTargetGenerateWholeProgram( - int targetIndex, - bool value) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL + setTargetProfile(int targetIndex, SlangProfileID profile) = 0; - virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceDXLayout(int targetIndex, bool value) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL + setTargetFlags(int targetIndex, SlangTargetFlags flags) = 0; - virtual SLANG_NO_THROW void SLANG_MCALL setTargetEmbedDownstreamIR(int targetIndex, bool value) = 0; - }; + /*! + @brief Set the floating point mode (e.g., precise or fast) to use a target. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + setTargetFloatingPointMode(int targetIndex, SlangFloatingPointMode mode) = 0; + + /* DEPRECATED: use `spSetMatrixLayoutMode` instead. */ + virtual SLANG_NO_THROW void SLANG_MCALL + setTargetMatrixLayoutMode(int targetIndex, SlangMatrixLayoutMode mode) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL setMatrixLayoutMode(SlangMatrixLayoutMode mode) = 0; + + /*! + @brief Set the level of debug information to produce. + */ + virtual SLANG_NO_THROW void SLANG_MCALL setDebugInfoLevel(SlangDebugInfoLevel level) = 0; + + /*! + @brief Set the level of optimization to perform. + */ + virtual SLANG_NO_THROW void SLANG_MCALL setOptimizationLevel(SlangOptimizationLevel level) = 0; + + + /*! + @brief Set the container format to be used for binary output. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + setOutputContainerFormat(SlangContainerFormat format) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL setPassThrough(SlangPassThrough passThrough) = 0; + + + virtual SLANG_NO_THROW void SLANG_MCALL + setDiagnosticCallback(SlangDiagnosticCallback callback, void const* userData) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL + setWriter(SlangWriterChannel channel, ISlangWriter* writer) = 0; + + virtual SLANG_NO_THROW ISlangWriter* SLANG_MCALL getWriter(SlangWriterChannel channel) = 0; + + /*! + @brief Add a path to use when searching for referenced files. + This will be used for both `#include` directives and also for explicit `__import` declarations. + @param ctx The compilation context. + @param searchDir The additional search directory. + */ + virtual SLANG_NO_THROW void SLANG_MCALL addSearchPath(const char* searchDir) = 0; + + /*! + @brief Add a macro definition to be used during preprocessing. + @param key The name of the macro to define. + @param value The value of the macro to define. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + addPreprocessorDefine(const char* key, const char* value) = 0; + + /*! + @brief Set options using arguments as if specified via command line. + @return Returns SlangResult. On success SLANG_SUCCEEDED(result) is true. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + processCommandLineArguments(char const* const* args, int argCount) = 0; + + /** Add a distinct translation unit to the compilation request + + `name` is optional. + Returns the zero-based index of the translation unit created. + */ + virtual SLANG_NO_THROW int SLANG_MCALL + addTranslationUnit(SlangSourceLanguage language, char const* name) = 0; + + + /** Set a default module name. Translation units will default to this module name if one is not + passed. If not set each translation unit will get a unique name. + */ + virtual SLANG_NO_THROW void SLANG_MCALL setDefaultModuleName(const char* defaultModuleName) = 0; + + /** Add a preprocessor definition that is scoped to a single translation unit. + + @param translationUnitIndex The index of the translation unit to get the definition. + @param key The name of the macro to define. + @param value The value of the macro to define. + */ + virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitPreprocessorDefine( + int translationUnitIndex, + const char* key, + const char* value) = 0; + + + /** Add a source file to the given translation unit. + + If a user-defined file system has been specified via + `spSetFileSystem`, then it will be used to load the + file at `path`. Otherwise, Slang will use the OS + file system. + + This function does *not* search for a file using + the registered search paths (`spAddSearchPath`), + and instead using the given `path` as-is. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + addTranslationUnitSourceFile(int translationUnitIndex, char const* path) = 0; + + /** Add a source string to the given translation unit. + + @param translationUnitIndex The index of the translation unit to add source to. + @param path The file-system path that should be assumed for the source code. + @param source A null-terminated UTF-8 encoded string of source code. + + The implementation will make a copy of the source code data. + An application may free the buffer immediately after this call returns. + + The `path` will be used in any diagnostic output, as well + as to determine the base path when resolving relative + `#include`s. + */ + virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceString( + int translationUnitIndex, + char const* path, + char const* source) = 0; + + + /** Add a slang library - such that its contents can be referenced during linking. + This is equivalent to the -r command line option. + + @param basePath The base path used to lookup referenced modules. + @param libData The library data + @param libDataSize The size of the library data + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + addLibraryReference(const char* basePath, const void* libData, size_t libDataSize) = 0; + + /** Add a source string to the given translation unit. + + @param translationUnitIndex The index of the translation unit to add source to. + @param path The file-system path that should be assumed for the source code. + @param sourceBegin A pointer to a buffer of UTF-8 encoded source code. + @param sourceEnd A pointer to to the end of the buffer specified in `sourceBegin` + + The implementation will make a copy of the source code data. + An application may free the buffer immediately after this call returns. + + The `path` will be used in any diagnostic output, as well + as to determine the base path when resolving relative + `#include`s. + */ + virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceStringSpan( + int translationUnitIndex, + char const* path, + char const* sourceBegin, + char const* sourceEnd) = 0; + + /** Add a blob of source code to the given translation unit. + + @param translationUnitIndex The index of the translation unit to add source to. + @param path The file-system path that should be assumed for the source code. + @param sourceBlob A blob containing UTF-8 encoded source code. + @param sourceEnd A pointer to to the end of the buffer specified in `sourceBegin` + + The compile request will retain a reference to the blob. + + The `path` will be used in any diagnostic output, as well + as to determine the base path when resolving relative + `#include`s. + */ + virtual SLANG_NO_THROW void SLANG_MCALL addTranslationUnitSourceBlob( + int translationUnitIndex, + char const* path, + ISlangBlob* sourceBlob) = 0; + + /** Add an entry point in a particular translation unit + */ + virtual SLANG_NO_THROW int SLANG_MCALL + addEntryPoint(int translationUnitIndex, char const* name, SlangStage stage) = 0; + + /** Add an entry point in a particular translation unit, + with additional arguments that specify the concrete + type names for entry-point generic type parameters. + */ + virtual SLANG_NO_THROW int SLANG_MCALL addEntryPointEx( + int translationUnitIndex, + char const* name, + SlangStage stage, + int genericArgCount, + char const** genericArgs) = 0; + + /** Specify the arguments to use for global generic parameters. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + setGlobalGenericArgs(int genericArgCount, char const** genericArgs) = 0; + + /** Specify the concrete type to be used for a global "existential slot." + + Every shader parameter (or leaf field of a `struct`-type shader parameter) + that has an interface or array-of-interface type introduces an existential + slot. The number of slots consumed by a shader parameter, and the starting + slot of each parameter can be queried via the reflection API using + `SLANG_PARAMETER_CATEGORY_EXISTENTIAL_TYPE_PARAM`. + + In order to generate specialized code, a concrete type needs to be specified + for each existential slot. This function specifies the name of the type + (or in general a type *expression*) to use for a specific slot at the + global scope. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + setTypeNameForGlobalExistentialTypeParam(int slotIndex, char const* typeName) = 0; + + /** Specify the concrete type to be used for an entry-point "existential slot." + + Every shader parameter (or leaf field of a `struct`-type shader parameter) + that has an interface or array-of-interface type introduces an existential + slot. The number of slots consumed by a shader parameter, and the starting + slot of each parameter can be queried via the reflection API using + `SLANG_PARAMETER_CATEGORY_EXISTENTIAL_TYPE_PARAM`. + + In order to generate specialized code, a concrete type needs to be specified + for each existential slot. This function specifies the name of the type + (or in general a type *expression*) to use for a specific slot at the + entry-point scope. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL setTypeNameForEntryPointExistentialTypeParam( + int entryPointIndex, + int slotIndex, + char const* typeName) = 0; + + /** Enable or disable an experimental, best-effort GLSL frontend + */ + virtual SLANG_NO_THROW void SLANG_MCALL setAllowGLSLInput(bool value) = 0; + + /** Execute the compilation request. + + @returns SlangResult, SLANG_OK on success. Use SLANG_SUCCEEDED() and SLANG_FAILED() to test + SlangResult. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile() = 0; + + + /** Get any diagnostic messages reported by the compiler. + + @returns A null-terminated UTF-8 encoded string of diagnostic messages. + + The returned pointer is only guaranteed to be valid + until `request` is destroyed. Applications that wish to + hold on to the diagnostic output for longer should use + `getDiagnosticOutputBlob`. + */ + virtual SLANG_NO_THROW char const* SLANG_MCALL getDiagnosticOutput() = 0; + + /** Get diagnostic messages reported by the compiler. + + @param outBlob A pointer to receive a blob holding a nul-terminated UTF-8 encoded string of + diagnostic messages. + @returns A `SlangResult` indicating success or failure. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getDiagnosticOutputBlob(ISlangBlob** outBlob) = 0; + + + /** Get the number of files that this compilation depended on. + + This includes both the explicit source files, as well as any + additional files that were transitively referenced (e.g., via + a `#include` directive). + */ + virtual SLANG_NO_THROW int SLANG_MCALL getDependencyFileCount() = 0; + + /** Get the path to a file this compilation depended on. + */ + virtual SLANG_NO_THROW char const* SLANG_MCALL getDependencyFilePath(int index) = 0; + + /** Get the number of translation units associated with the compilation request + */ + virtual SLANG_NO_THROW int SLANG_MCALL getTranslationUnitCount() = 0; + + /** Get the output source code associated with a specific entry point. + + The lifetime of the output pointer is the same as `request`. + */ + virtual SLANG_NO_THROW char const* SLANG_MCALL getEntryPointSource(int entryPointIndex) = 0; + + /** Get the output bytecode associated with a specific entry point. + + The lifetime of the output pointer is the same as `request`. + */ + virtual SLANG_NO_THROW void const* SLANG_MCALL + getEntryPointCode(int entryPointIndex, size_t* outSize) = 0; + + /** Get the output code associated with a specific entry point. + + @param entryPointIndex The index of the entry point to get code for. + @param targetIndex The index of the target to get code for (default: zero). + @param outBlob A pointer that will receive the blob of code + @returns A `SlangResult` to indicate success or failure. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getEntryPointCodeBlob(int entryPointIndex, int targetIndex, ISlangBlob** outBlob) = 0; + + /** Get entry point 'callable' functions accessible through the ISlangSharedLibrary interface. + + That the functions remain in scope as long as the ISlangSharedLibrary interface is in scope. + + NOTE! Requires a compilation target of SLANG_HOST_CALLABLE. + + @param entryPointIndex The index of the entry point to get code for. + @param targetIndex The index of the target to get code for (default: zero). + @param outSharedLibrary A pointer to a ISharedLibrary interface which functions can be queried + on. + @returns A `SlangResult` to indicate success or failure. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointHostCallable( + int entryPointIndex, + int targetIndex, + ISlangSharedLibrary** outSharedLibrary) = 0; + + /** Get the output code associated with a specific target. + + @param targetIndex The index of the target to get code for (default: zero). + @param outBlob A pointer that will receive the blob of code + @returns A `SlangResult` to indicate success or failure. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getTargetCodeBlob(int targetIndex, ISlangBlob** outBlob) = 0; + + /** Get 'callable' functions for a target accessible through the ISlangSharedLibrary interface. + + That the functions remain in scope as long as the ISlangSharedLibrary interface is in scope. + + NOTE! Requires a compilation target of SLANG_HOST_CALLABLE. + + @param targetIndex The index of the target to get code for (default: zero). + @param outSharedLibrary A pointer to a ISharedLibrary interface which functions can be queried + on. + @returns A `SlangResult` to indicate success or failure. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getTargetHostCallable(int targetIndex, ISlangSharedLibrary** outSharedLibrary) = 0; + + /** Get the output bytecode associated with an entire compile request. + + The lifetime of the output pointer is the same as `request` and the last spCompile. + + @param outSize The size of the containers contents in bytes. Will be zero if there is + no code available. + @returns Pointer to start of the contained data, or nullptr if there is no code + available. + */ + virtual SLANG_NO_THROW void const* SLANG_MCALL getCompileRequestCode(size_t* outSize) = 0; + + /** Get the compilation result as a file system. + The result is not written to the actual OS file system, but is made avaiable as an + in memory representation. + */ + virtual SLANG_NO_THROW ISlangMutableFileSystem* SLANG_MCALL + getCompileRequestResultAsFileSystem() = 0; + + /** Return the container code as a blob. The container blob is created as part of a compilation + (with spCompile), and a container is produced with a suitable ContainerFormat. + + @param outSize The blob containing the container data. + @returns A `SlangResult` to indicate success or failure. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getContainerCode(ISlangBlob** outBlob) = 0; + + /** Load repro from memory specified. + + Should only be performed on a newly created request. + + NOTE! When using the fileSystem, files will be loaded via their `unique names` as if they are + part of the flat file system. This mechanism is described more fully in docs/repro.md. + + @param fileSystem An (optional) filesystem. Pass nullptr to just use contents of repro + held in data. + @param data The data to load from. + @param size The size of the data to load from. + @returns A `SlangResult` to indicate success or failure. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + loadRepro(ISlangFileSystem* fileSystem, const void* data, size_t size) = 0; + + /** Save repro state. Should *typically* be performed after spCompile, so that everything + that is needed for a compilation is available. + + @param outBlob Blob that will hold the serialized state + @returns A `SlangResult` to indicate success or failure. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveRepro(ISlangBlob** outBlob) = 0; + + /** Enable repro capture. + + Should be set after any ISlangFileSystem has been set, but before any compilation. It ensures + that everything that the ISlangFileSystem accesses will be correctly recorded. Note that if a + ISlangFileSystem/ISlangFileSystemExt isn't explicitly set (ie the default is used), then the + request will automatically be set up to record everything appropriate. + + @returns A `SlangResult` to indicate success or failure. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL enableReproCapture() = 0; + + /** Get the (linked) program for a compile request. + + The linked program will include all of the global-scope modules for the + translation units in the program, plus any modules that they `import` + (transitively), specialized to any global specialization arguments that + were provided via the API. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getProgram(slang::IComponentType** outProgram) = 0; + + /** Get the (partially linked) component type for an entry point. + + The returned component type will include the entry point at the + given index, and will be specialized using any specialization arguments + that were provided for it via the API. + + The returned component will *not* include the modules representing + the global scope and its dependencies/specialization, so a client + program will typically want to compose this component type with + the one returned by `spCompileRequest_getProgram` to get a complete + and usable component type from which kernel code can be requested. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getEntryPoint(SlangInt entryPointIndex, slang::IComponentType** outEntryPoint) = 0; + + /** Get the (un-linked) module for a translation unit. + + The returned module will not be linked against any dependencies, + nor against any entry points (even entry points declared inside + the module). Similarly, the module will not be specialized + to the arguments that might have been provided via the API. + + This function provides an atomic unit of loaded code that + is suitable for looking up types and entry points in the + given module, and for linking together to produce a composite + program that matches the needs of an application. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getModule(SlangInt translationUnitIndex, slang::IModule** outModule) = 0; + + /** Get the `ISession` handle behind the `SlangCompileRequest`. + TODO(JS): Arguably this should just return the session pointer. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getSession(slang::ISession** outSession) = 0; + + /** get reflection data from a compilation request */ + virtual SLANG_NO_THROW SlangReflection* SLANG_MCALL getReflection() = 0; + + /** Make output specially handled for command line output */ + virtual SLANG_NO_THROW void SLANG_MCALL setCommandLineCompilerMode() = 0; + + /** Add a defined capability that should be assumed available on the target */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + addTargetCapability(SlangInt targetIndex, SlangCapabilityID capability) = 0; + + /** Get the (linked) program for a compile request, including all entry points. + + The resulting program will include all of the global-scope modules for the + translation units in the program, plus any modules that they `import` + (transitively), specialized to any global specialization arguments that + were provided via the API, as well as all entry points specified for compilation, + specialized to their entry-point specialization arguments. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getProgramWithEntryPoints(slang::IComponentType** outProgram) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL isParameterLocationUsed( + SlangInt entryPointIndex, + SlangInt targetIndex, + SlangParameterCategory category, + SlangUInt spaceIndex, + SlangUInt registerIndex, + bool& outUsed) = 0; + + /** Set the line directive mode for a target. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + setTargetLineDirectiveMode(SlangInt targetIndex, SlangLineDirectiveMode mode) = 0; + + /** Set whether to use scalar buffer layouts for GLSL/Vulkan targets. + If true, the generated GLSL/Vulkan code will use `scalar` layout for storage buffers. + If false, the resulting code will std430 for storage buffers. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + setTargetForceGLSLScalarBufferLayout(int targetIndex, bool forceScalarLayout) = 0; + + /** Overrides the severity of a specific diagnostic message. + + @param messageID Numeric identifier of the message to override, + as defined in the 1st parameter of the DIAGNOSTIC macro. + @param overrideSeverity New severity of the message. If the message is originally Error or + Fatal, the new severity cannot be lower than that. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + overrideDiagnosticSeverity(SlangInt messageID, SlangSeverity overrideSeverity) = 0; + + /** Returns the currently active flags of the request's diagnostic sink. */ + virtual SLANG_NO_THROW SlangDiagnosticFlags SLANG_MCALL getDiagnosticFlags() = 0; + + /** Sets the flags of the request's diagnostic sink. + The previously specified flags are discarded. */ + virtual SLANG_NO_THROW void SLANG_MCALL setDiagnosticFlags(SlangDiagnosticFlags flags) = 0; + + /** Set the debug format to be used for debugging information */ + virtual SLANG_NO_THROW void SLANG_MCALL + setDebugInfoFormat(SlangDebugInfoFormat debugFormat) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL setEnableEffectAnnotations(bool value) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL setReportDownstreamTime(bool value) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL setReportPerfBenchmark(bool value) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL setSkipSPIRVValidation(bool value) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL + setTargetUseMinimumSlangOptimization(int targetIndex, bool value) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL setIgnoreCapabilityCheck(bool value) = 0; + + // return a copy of internal profiling results, and if `shouldClear` is true, clear the internal + // profiling results before returning. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getCompileTimeProfile(ISlangProfiler** compileTimeProfile, bool shouldClear) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL + setTargetGenerateWholeProgram(int targetIndex, bool value) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL setTargetForceDXLayout(int targetIndex, bool value) = 0; + + virtual SLANG_NO_THROW void SLANG_MCALL + setTargetEmbedDownstreamIR(int targetIndex, bool value) = 0; +}; #define SLANG_UUID_ICompileRequest ICompileRequest::getTypeGuid() -} +} // namespace slang #endif diff --git a/include/slang-gfx.h b/include/slang-gfx.h index 7756d76da..6f46fed33 100644 --- a/include/slang-gfx.h +++ b/include/slang-gfx.h @@ -1,30 +1,30 @@ // render.h #pragma once -#include -#include - -#include "slang.h" #include "slang-com-ptr.h" +#include "slang.h" + +#include +#include #if defined(SLANG_GFX_DYNAMIC) -# if defined(_MSC_VER) -# ifdef SLANG_GFX_DYNAMIC_EXPORT -# define SLANG_GFX_API SLANG_DLL_EXPORT -# else -# define SLANG_GFX_API __declspec(dllimport) -# endif -# else -// TODO: need to consider compiler capabilities -//# ifdef SLANG_DYNAMIC_EXPORT -# define SLANG_GFX_API SLANG_DLL_EXPORT -//# endif -# endif + #if defined(_MSC_VER) + #ifdef SLANG_GFX_DYNAMIC_EXPORT + #define SLANG_GFX_API SLANG_DLL_EXPORT + #else + #define SLANG_GFX_API __declspec(dllimport) + #endif + #else + // TODO: need to consider compiler capabilities + // # ifdef SLANG_DYNAMIC_EXPORT + #define SLANG_GFX_API SLANG_DLL_EXPORT + // # endif + #endif #endif #ifndef SLANG_GFX_API -# define SLANG_GFX_API + #define SLANG_GFX_API #endif // Needed for building on cygwin with gcc @@ -34,10 +34,13 @@ // GLOBAL TODO: doc comments // GLOBAL TODO: Rationalize integer types (not a smush of uint/int/Uint/Int/etc) // - need typedefs in gfx namespace for Count, Index, Size, Offset (ex. DeviceAddress) -// - Index and Count are for arrays, and indexing into array - like things(XY coordinates of pixels, etc.) -// - Count is also for anything where we need to measure how many of something there are. This includes things like extents. +// - Index and Count are for arrays, and indexing into array - like things(XY coordinates of +// pixels, etc.) +// - Count is also for anything where we need to measure how many of something there are. +// This includes things like extents. // - Offset and Size are almost always for bytes and things measured in bytes. -namespace gfx { +namespace gfx +{ using Slang::ComPtr; @@ -56,7 +59,10 @@ const uint64_t kTimeoutInfinite = 0xFFFFFFFFFFFFFFFF; enum class StructType { - D3D12DeviceExtendedDesc, D3D12ExperimentalFeaturesDesc, SlangSessionExtendedDesc, RayTracingValidationDesc + D3D12DeviceExtendedDesc, + D3D12ExperimentalFeaturesDesc, + SlangSessionExtendedDesc, + RayTracingValidationDesc }; // TODO: Rename to Stage @@ -136,23 +142,24 @@ class ITransientResourceHeap; enum class ShaderModuleSourceType { - SlangSource, // a slang source string in memory. - SlangModuleBinary, // a slang module binary code in memory. - SlangSourceFile, // a slang source from file. + SlangSource, // a slang source string in memory. + SlangModuleBinary, // a slang module binary code in memory. + SlangSourceFile, // a slang source from file. SlangModuleBinaryFile, // a slang module binary code from file. }; -class IShaderProgram: public ISlangUnknown +class IShaderProgram : public ISlangUnknown { public: // Defines how linking should be performed for a shader program. enum class LinkingStyle { - // Compose all entry-points in a single program, then compile all entry-points together with the same - // set of root shader arguments. + // Compose all entry-points in a single program, then compile all entry-points together with + // the same set of root shader arguments. SingleProgram, - // Link and compile each entry-point individually, potentially with different specializations. + // Link and compile each entry-point individually, potentially with different + // specializations. SeparateEntryPointCompilation }; @@ -163,7 +170,7 @@ public: LinkingStyle linkingStyle = LinkingStyle::SingleProgram; // The global scope or a Slang composite component that represents the entire program. - slang::IComponentType* slangGlobalScope; + slang::IComponentType* slangGlobalScope; // Number of separate entry point components in the `slangEntryPoints` array to link in. // If set to 0, then `slangGlobalScope` must contain Slang EntryPoint components. @@ -191,9 +198,12 @@ public: virtual SLANG_NO_THROW slang::TypeReflection* SLANG_MCALL findTypeByName(const char* name) = 0; }; -#define SLANG_UUID_IShaderProgram \ - { \ - 0x9d32d0ad, 0x915c, 0x4ffd, { 0x91, 0xe2, 0x50, 0x85, 0x54, 0xa0, 0x4a, 0x76 } \ +#define SLANG_UUID_IShaderProgram \ + { \ + 0x9d32d0ad, 0x915c, 0x4ffd, \ + { \ + 0x91, 0xe2, 0x50, 0x85, 0x54, 0xa0, 0x4a, 0x76 \ + } \ } // TODO: Confirm with Yong that we really want this naming convention @@ -311,12 +321,14 @@ public: // TODO: This should be generated from above // TODO: enum class should be explicitly uint32_t or whatever's appropriate /// Different formats of things like pixels or elements of vertices -/// NOTE! Any change to this type (adding, removing, changing order) - must also be reflected in changes GFX_FORMAT +/// NOTE! Any change to this type (adding, removing, changing order) - must also be reflected in +/// changes GFX_FORMAT enum class Format { // D3D formats omitted: 19-22, 44-47, 65-66, 68-70, 73, 76, 79, 82, 88-89, 92-94, 97, 100-114 - // These formats are omitted due to lack of a corresponding Vulkan format. D24_UNORM_S8_UINT (DXGI_FORMAT 45) - // has a matching Vulkan format but is also omitted as it is only supported by Nvidia. + // These formats are omitted due to lack of a corresponding Vulkan format. D24_UNORM_S8_UINT + // (DXGI_FORMAT 45) has a matching Vulkan format but is also omitted as it is only supported by + // Nvidia. Unknown, R32G32B32A32_TYPELESS, @@ -420,7 +432,7 @@ enum class Format BC7_UNORM_SRGB, R64_UINT, - + R64_SINT, _Count, @@ -433,27 +445,32 @@ enum class Format // TODO: Width/Height/Depth/whatever should not be used. We should use extentX, extentY, etc. struct FormatInfo { - GfxCount channelCount; ///< The amount of channels in the format. Only set if the channelType is set - uint8_t channelType; ///< One of SlangScalarType None if type isn't made up of elements of type. TODO: Change to uint32_t? + GfxCount + channelCount; ///< The amount of channels in the format. Only set if the channelType is set + uint8_t channelType; ///< One of SlangScalarType None if type isn't made up of elements of type. + ///< TODO: Change to uint32_t? - Size blockSizeInBytes; ///< The size of a block in bytes. - GfxCount pixelsPerBlock; ///< The number of pixels contained in a block. - GfxCount blockWidth; ///< The width of a block in pixels. - GfxCount blockHeight; ///< The height of a block in pixels. + Size blockSizeInBytes; ///< The size of a block in bytes. + GfxCount pixelsPerBlock; ///< The number of pixels contained in a block. + GfxCount blockWidth; ///< The width of a block in pixels. + GfxCount blockHeight; ///< The height of a block in pixels. }; enum class InputSlotClass { - PerVertex, PerInstance + PerVertex, + PerInstance }; struct InputElementDesc { - char const* semanticName; ///< The name of the corresponding parameter in shader code. - GfxIndex semanticIndex; ///< The index of the corresponding parameter in shader code. Only needed if multiple parameters share a semantic name. - Format format; ///< The format of the data being fetched for this element. - Offset offset; ///< The offset in bytes of this element from the start of the corresponding chunk of vertex stream data. - GfxIndex bufferSlotIndex; ///< The index of the vertex stream to fetch this element's data from. + char const* semanticName; ///< The name of the corresponding parameter in shader code. + GfxIndex semanticIndex; ///< The index of the corresponding parameter in shader code. Only + ///< needed if multiple parameters share a semantic name. + Format format; ///< The format of the data being fetched for this element. + Offset offset; ///< The offset in bytes of this element from the start of the corresponding + ///< chunk of vertex stream data. + GfxIndex bufferSlotIndex; ///< The index of the vertex stream to fetch this element's data from. }; struct VertexStreamDesc @@ -465,12 +482,19 @@ struct VertexStreamDesc enum class PrimitiveType { - Point, Line, Triangle, Patch + Point, + Line, + Triangle, + Patch }; enum class PrimitiveTopology { - TriangleList, TriangleStrip, PointList, LineList, LineStrip + TriangleList, + TriangleStrip, + PointList, + LineList, + LineStrip }; enum class ResourceState @@ -504,18 +528,24 @@ struct ResourceStateSet { public: void add(ResourceState state) { m_bitFields |= (1LL << (uint32_t)state); } - template void add(ResourceState s, TResourceState... states) + template + void add(ResourceState s, TResourceState... states) { add(s); add(states...); } - bool contains(ResourceState state) const { return (m_bitFields & (1LL << (uint32_t)state)) != 0; } + bool contains(ResourceState state) const + { + return (m_bitFields & (1LL << (uint32_t)state)) != 0; + } ResourceStateSet() : m_bitFields(0) - {} + { + } ResourceStateSet(const ResourceStateSet& other) = default; ResourceStateSet(ResourceState state) { add(state); } - template ResourceStateSet(TResourceState... states) + template + ResourceStateSet(TResourceState... states) { add(states...); } @@ -544,14 +574,14 @@ enum class MemoryType enum class InteropHandleAPI { Unknown, - D3D12, // A D3D12 object pointer. - Vulkan, // A general Vulkan object handle. - CUDA, // A general CUDA object handle. - Win32, // A general Win32 HANDLE. - FileDescriptor, // A file descriptor. - DeviceAddress, // A device address. + D3D12, // A D3D12 object pointer. + Vulkan, // A general Vulkan object handle. + CUDA, // A general CUDA object handle. + Win32, // A general Win32 HANDLE. + FileDescriptor, // A file descriptor. + DeviceAddress, // A device address. D3D12CpuDescriptorHandle, // A D3D12_CPU_DESCRIPTOR_HANDLE value. - Metal, // A general Metal object handle. + Metal, // A general Metal object handle. }; struct InteropHandle @@ -572,28 +602,32 @@ public: GfxCount vertexStreamCount = 0; }; }; -#define SLANG_UUID_IInputLayout \ - { \ - 0x45223711, 0xa84b, 0x455c, { 0xbe, 0xfa, 0x49, 0x37, 0x42, 0x1e, 0x8e, 0x2e } \ +#define SLANG_UUID_IInputLayout \ + { \ + 0x45223711, 0xa84b, 0x455c, \ + { \ + 0xbe, 0xfa, 0x49, 0x37, 0x42, 0x1e, 0x8e, 0x2e \ + } \ } -class IResource: public ISlangUnknown +class IResource : public ISlangUnknown { public: - /// The type of resource. - /// NOTE! The order needs to be such that all texture types are at or after Texture1D (otherwise isTexture won't work correctly) + /// The type of resource. + /// NOTE! The order needs to be such that all texture types are at or after Texture1D (otherwise + /// isTexture won't work correctly) enum class Type { - Unknown, ///< Unknown - Buffer, ///< A buffer (like a constant/index/vertex buffer) - Texture1D, ///< A 1d texture - Texture2D, ///< A 2d texture - Texture3D, ///< A 3d texture - TextureCube, ///< A cubemap consists of 6 Texture2D like faces + Unknown, ///< Unknown + Buffer, ///< A buffer (like a constant/index/vertex buffer) + Texture1D, ///< A 1d texture + Texture2D, ///< A 2d texture + Texture3D, ///< A 3d texture + TextureCube, ///< A cubemap consists of 6 Texture2D like faces _Count, }; - /// Base class for Descs + /// Base class for Descs struct DescBase { Type type = Type::Unknown; @@ -610,11 +644,13 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL setDebugName(const char* name) = 0; virtual SLANG_NO_THROW const char* SLANG_MCALL getDebugName() = 0; - }; -#define SLANG_UUID_IResource \ - { \ - 0xa0e39f34, 0x8398, 0x4522, { 0x95, 0xc2, 0xeb, 0xc0, 0xf9, 0x84, 0xef, 0x3f } \ +#define SLANG_UUID_IResource \ + { \ + 0xa0e39f34, 0x8398, 0x4522, \ + { \ + 0x95, 0xc2, 0xeb, 0xc0, 0xf9, 0x84, 0xef, 0x3f \ + } \ } struct MemoryRange @@ -624,13 +660,13 @@ struct MemoryRange uint64_t size; }; -class IBufferResource: public IResource +class IBufferResource : public IResource { public: - struct Desc: public DescBase + struct Desc : public DescBase { - Size sizeInBytes = 0; ///< Total size in bytes - Size elementSize = 0; ///< Get the element stride. If > 0, this is a structured buffer + Size sizeInBytes = 0; ///< Total size in bytes + Size elementSize = 0; ///< Get the element stride. If > 0, this is a structured buffer Format format = Format::Unknown; }; @@ -639,9 +675,12 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL map(MemoryRange* rangeToRead, void** outPointer) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL unmap(MemoryRange* writtenRange) = 0; }; -#define SLANG_UUID_IBufferResource \ - { \ - 0x1b274efe, 0x5e37, 0x492b, { 0x82, 0x6e, 0x7e, 0xe7, 0xe8, 0xf5, 0xa4, 0x9b } \ +#define SLANG_UUID_IBufferResource \ + { \ + 0x1b274efe, 0x5e37, 0x492b, \ + { \ + 0x82, 0x6e, 0x7e, 0xe7, 0xe8, 0xf5, 0xa4, 0x9b \ + } \ } struct DepthStencilClearValue @@ -662,8 +701,8 @@ struct ClearValue struct BufferRange { - Offset offset; ///< Offset in bytes. - Size size; ///< Size in bytes. + Offset offset; ///< Offset in bytes. + Size size; ///< Size in bytes. }; enum class TextureAspect : uint32_t @@ -686,10 +725,10 @@ struct SubresourceRange GfxIndex mipLevel; GfxCount mipLevelCount; GfxIndex baseArrayLayer; // For Texture3D, this is WSlice. - GfxCount layerCount; // For cube maps, this is a multiple of 6. + GfxCount layerCount; // For cube maps, this is a multiple of 6. }; -class ITextureResource: public IResource +class ITextureResource : public IResource { public: static const GfxCount kRemainingTextureSize = 0xffffffff; @@ -699,97 +738,103 @@ public: GfxIndex y = 0; GfxIndex z = 0; Offset3D() = default; - Offset3D(GfxIndex _x, GfxIndex _y, GfxIndex _z) :x(_x), y(_y), z(_z) {} + Offset3D(GfxIndex _x, GfxIndex _y, GfxIndex _z) + : x(_x), y(_y), z(_z) + { + } }; struct SampleDesc { - GfxCount numSamples = 1; ///< Number of samples per pixel - int quality = 0; ///< The quality measure for the samples + GfxCount numSamples = 1; ///< Number of samples per pixel + int quality = 0; ///< The quality measure for the samples }; struct Extents { - GfxCount width = 0; ///< Width in pixels - GfxCount height = 0; ///< Height in pixels (if 2d or 3d) - GfxCount depth = 0; ///< Depth (if 3d) + GfxCount width = 0; ///< Width in pixels + GfxCount height = 0; ///< Height in pixels (if 2d or 3d) + GfxCount depth = 0; ///< Depth (if 3d) }; - struct Desc: public DescBase + struct Desc : public DescBase { Extents size; - GfxCount arraySize = 0; ///< Array size + GfxCount arraySize = 0; ///< Array size - GfxCount numMipLevels = 0; ///< Number of mip levels - if 0 will create all mip levels - Format format; ///< The resources format - SampleDesc sampleDesc; ///< How the resource is sampled + GfxCount numMipLevels = 0; ///< Number of mip levels - if 0 will create all mip levels + Format format; ///< The resources format + SampleDesc sampleDesc; ///< How the resource is sampled ClearValue* optimalClearValue = nullptr; }; - /// Data for a single subresource of a texture. - /// - /// Each subresource is a tensor with `1 <= rank <= 3`, - /// where the rank is deterined by the base shape of the - /// texture (Buffer, 1D, 2D, 3D, or Cube). For the common - /// case of a 2D texture, `rank == 2` and each subresource - /// is a 2D image. - /// - /// Subresource tensors must be stored in a row-major layout, - /// so that the X axis strides over texels, the Y axis strides - /// over 1D rows of texels, and the Z axis strides over 2D - /// "layers" of texels. - /// - /// For a texture with multiple mip levels or array elements, - /// each mip level and array element is stores as a distinct - /// subresource. When indexing into an array of subresources, - /// the index of a subresoruce for mip level `m` and array - /// index `a` is `m + a*mipLevelCount`. - /// + /// Data for a single subresource of a texture. + /// + /// Each subresource is a tensor with `1 <= rank <= 3`, + /// where the rank is deterined by the base shape of the + /// texture (Buffer, 1D, 2D, 3D, or Cube). For the common + /// case of a 2D texture, `rank == 2` and each subresource + /// is a 2D image. + /// + /// Subresource tensors must be stored in a row-major layout, + /// so that the X axis strides over texels, the Y axis strides + /// over 1D rows of texels, and the Z axis strides over 2D + /// "layers" of texels. + /// + /// For a texture with multiple mip levels or array elements, + /// each mip level and array element is stores as a distinct + /// subresource. When indexing into an array of subresources, + /// the index of a subresoruce for mip level `m` and array + /// index `a` is `m + a*mipLevelCount`. + /// struct SubresourceData { - /// Pointer to texel data for the subresource tensor. + /// Pointer to texel data for the subresource tensor. void const* data; - /// Stride in bytes between rows of the subresource tensor. - /// - /// This is the number of bytes to add to a pointer to a texel - /// at (X,Y,Z) to get to a texel at (X,Y+1,Z). - /// - /// Devices may not support all possible values for `strideY`. - /// In particular, they may only support strictly positive strides. - /// + /// Stride in bytes between rows of the subresource tensor. + /// + /// This is the number of bytes to add to a pointer to a texel + /// at (X,Y,Z) to get to a texel at (X,Y+1,Z). + /// + /// Devices may not support all possible values for `strideY`. + /// In particular, they may only support strictly positive strides. + /// gfx::Size strideY; - /// Stride in bytes between layers of the subresource tensor. - /// - /// This is the number of bytes to add to a pointer to a texel - /// at (X,Y,Z) to get to a texel at (X,Y,Z+1). - /// - /// Devices may not support all possible values for `strideZ`. - /// In particular, they may only support strictly positive strides. - /// + /// Stride in bytes between layers of the subresource tensor. + /// + /// This is the number of bytes to add to a pointer to a texel + /// at (X,Y,Z) to get to a texel at (X,Y,Z+1). + /// + /// Devices may not support all possible values for `strideZ`. + /// In particular, they may only support strictly positive strides. + /// gfx::Size strideZ; }; virtual SLANG_NO_THROW Desc* SLANG_MCALL getDesc() = 0; }; -#define SLANG_UUID_ITextureResource \ - { \ - 0xcf88a31c, 0x6187, 0x46c5, { 0xa4, 0xb7, 0xeb, 0x58, 0xc7, 0x33, 0x40, 0x17 } \ +#define SLANG_UUID_ITextureResource \ + { \ + 0xcf88a31c, 0x6187, 0x46c5, \ + { \ + 0xa4, 0xb7, 0xeb, 0x58, 0xc7, 0x33, 0x40, 0x17 \ + } \ } enum class ComparisonFunc : uint8_t { - Never = 0x0, - Less = 0x1, - Equal = 0x2, - LessEqual = 0x3, - Greater = 0x4, - NotEqual = 0x5, - GreaterEqual = 0x6, - Always = 0x7, + Never = 0x0, + Less = 0x1, + Equal = 0x2, + LessEqual = 0x3, + Greater = 0x4, + NotEqual = 0x5, + GreaterEqual = 0x6, + Always = 0x7, }; enum class TextureFilteringMode @@ -820,19 +865,19 @@ class ISamplerState : public ISlangUnknown public: struct Desc { - TextureFilteringMode minFilter = TextureFilteringMode::Linear; - TextureFilteringMode magFilter = TextureFilteringMode::Linear; - TextureFilteringMode mipFilter = TextureFilteringMode::Linear; - TextureReductionOp reductionOp = TextureReductionOp::Average; - TextureAddressingMode addressU = TextureAddressingMode::Wrap; - TextureAddressingMode addressV = TextureAddressingMode::Wrap; - TextureAddressingMode addressW = TextureAddressingMode::Wrap; - float mipLODBias = 0.0f; - uint32_t maxAnisotropy = 1; - ComparisonFunc comparisonFunc = ComparisonFunc::Never; - float borderColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; - float minLOD = -FLT_MAX; - float maxLOD = FLT_MAX; + TextureFilteringMode minFilter = TextureFilteringMode::Linear; + TextureFilteringMode magFilter = TextureFilteringMode::Linear; + TextureFilteringMode mipFilter = TextureFilteringMode::Linear; + TextureReductionOp reductionOp = TextureReductionOp::Average; + TextureAddressingMode addressU = TextureAddressingMode::Wrap; + TextureAddressingMode addressV = TextureAddressingMode::Wrap; + TextureAddressingMode addressW = TextureAddressingMode::Wrap; + float mipLODBias = 0.0f; + uint32_t maxAnisotropy = 1; + ComparisonFunc comparisonFunc = ComparisonFunc::Never; + float borderColor[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + float minLOD = -FLT_MAX; + float maxLOD = FLT_MAX; }; /// Returns a native API handle representing this sampler state object. @@ -840,9 +885,12 @@ public: /// When using Vulkan, this will be a VkSampler. virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outNativeHandle) = 0; }; -#define SLANG_UUID_ISamplerState \ - { \ - 0x8b8055df, 0x9377, 0x401d, { 0x91, 0xff, 0x3f, 0xa3, 0xbf, 0x66, 0x64, 0xf4 } \ +#define SLANG_UUID_ISamplerState \ + { \ + 0x8b8055df, 0x9377, 0x401d, \ + { \ + 0x91, 0xff, 0x3f, 0xa3, 0xbf, 0x66, 0x64, 0xf4 \ + } \ } class IResourceView : public ISlangUnknown @@ -869,12 +917,13 @@ public: struct Desc { - Type type; - Format format; + Type type; + Format format; // Required fields for `RenderTarget` and `DepthStencil` views. RenderTargetDesc renderTarget; - // Specifies the range of a texture resource for a ShaderRsource/UnorderedAccess/RenderTarget/DepthStencil view. + // Specifies the range of a texture resource for a + // ShaderRsource/UnorderedAccess/RenderTarget/DepthStencil view. SubresourceRange subresourceRange; // Specifies the range of a buffer resource for a ShaderResource/UnorderedAccess view. BufferRange bufferRange; @@ -882,15 +931,18 @@ public: virtual SLANG_NO_THROW Desc* SLANG_MCALL getViewDesc() = 0; /// Returns a native API handle representing this resource view object. - /// When using D3D12, this will be a D3D12_CPU_DESCRIPTOR_HANDLE or a buffer device address depending - /// on the type of the resource view. - /// When using Vulkan, this will be a VkImageView, VkBufferView, VkAccelerationStructure or a VkBuffer - /// depending on the type of the resource view. + /// When using D3D12, this will be a D3D12_CPU_DESCRIPTOR_HANDLE or a buffer device address + /// depending on the type of the resource view. When using Vulkan, this will be a VkImageView, + /// VkBufferView, VkAccelerationStructure or a VkBuffer depending on the type of the resource + /// view. virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outNativeHandle) = 0; }; -#define SLANG_UUID_IResourceView \ - { \ - 0x7b6c4926, 0x884, 0x408c, { 0xad, 0x8a, 0x50, 0x3a, 0x8e, 0x23, 0x98, 0xa4 } \ +#define SLANG_UUID_IResourceView \ + { \ + 0x7b6c4926, 0x884, 0x408c, \ + { \ + 0xad, 0x8a, 0x50, 0x3a, 0x8e, 0x23, 0x98, 0xa4 \ + } \ } class IAccelerationStructure : public IResourceView @@ -920,7 +972,8 @@ public: enum class GeometryType { - Triangles, ProcedurePrimitives + Triangles, + ProcedurePrimitives }; struct GeometryFlags @@ -1049,9 +1102,12 @@ public: virtual SLANG_NO_THROW DeviceAddress SLANG_MCALL getDeviceAddress() = 0; }; -#define SLANG_UUID_IAccelerationStructure \ - { \ - 0xa5cdda3c, 0x1d4e, 0x4df7, { 0x8e, 0xf2, 0xb7, 0x3f, 0xce, 0x4, 0xde, 0x3b } \ +#define SLANG_UUID_IAccelerationStructure \ + { \ + 0xa5cdda3c, 0x1d4e, 0x4df7, \ + { \ + 0x8e, 0xf2, 0xb7, 0x3f, 0xce, 0x4, 0xde, 0x3b \ + } \ } class IFence : public ISlangUnknown @@ -1072,9 +1128,12 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL getSharedHandle(InteropHandle* outHandle) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outNativeHandle) = 0; }; -#define SLANG_UUID_IFence \ - { \ - 0x7fe1c283, 0xd3f4, 0x48ed, { 0xaa, 0xf3, 0x1, 0x51, 0x96, 0x4e, 0x7c, 0xb5 } \ +#define SLANG_UUID_IFence \ + { \ + 0x7fe1c283, 0xd3f4, 0x48ed, \ + { \ + 0xaa, 0xf3, 0x1, 0x51, 0x96, 0x4e, 0x7c, 0xb5 \ + } \ } struct ShaderOffset @@ -1088,14 +1147,11 @@ struct ShaderOffset } bool operator==(const ShaderOffset& other) const { - return uniformOffset == other.uniformOffset - && bindingRangeIndex == other.bindingRangeIndex - && bindingArrayIndex == other.bindingArrayIndex; - } - bool operator!=(const ShaderOffset& other) const - { - return !this->operator==(other); + return uniformOffset == other.uniformOffset && + bindingRangeIndex == other.bindingRangeIndex && + bindingArrayIndex == other.bindingArrayIndex; } + bool operator!=(const ShaderOffset& other) const { return !this->operator==(other); } bool operator<(const ShaderOffset& other) const { if (bindingRangeIndex < other.bindingRangeIndex) @@ -1115,7 +1171,9 @@ struct ShaderOffset enum class ShaderObjectContainerType { - None, Array, StructuredBuffer + None, + Array, + StructuredBuffer }; class IShaderObject : public ISlangUnknown @@ -1125,38 +1183,40 @@ public: virtual SLANG_NO_THROW ShaderObjectContainerType SLANG_MCALL getContainerType() = 0; virtual SLANG_NO_THROW GfxCount SLANG_MCALL getEntryPointCount() = 0; virtual SLANG_NO_THROW Result SLANG_MCALL - getEntryPoint(GfxIndex index, IShaderObject** entryPoint) = 0; + getEntryPoint(GfxIndex index, IShaderObject** entryPoint) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL - setData(ShaderOffset const& offset, void const* data, Size size) = 0; + setData(ShaderOffset const& offset, void const* data, Size size) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL - getObject(ShaderOffset const& offset, IShaderObject** object) = 0; + getObject(ShaderOffset const& offset, IShaderObject** object) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL - setObject(ShaderOffset const& offset, IShaderObject* object) = 0; + setObject(ShaderOffset const& offset, IShaderObject* object) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL - setResource(ShaderOffset const& offset, IResourceView* resourceView) = 0; + setResource(ShaderOffset const& offset, IResourceView* resourceView) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL - setSampler(ShaderOffset const& offset, ISamplerState* sampler) = 0; + setSampler(ShaderOffset const& offset, ISamplerState* sampler) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL setCombinedTextureSampler( - ShaderOffset const& offset, IResourceView* textureView, ISamplerState* sampler) = 0; + ShaderOffset const& offset, + IResourceView* textureView, + ISamplerState* sampler) = 0; - /// Manually overrides the specialization argument for the sub-object binding at `offset`. - /// Specialization arguments are passed to the shader compiler to specialize the type - /// of interface-typed shader parameters. + /// Manually overrides the specialization argument for the sub-object binding at `offset`. + /// Specialization arguments are passed to the shader compiler to specialize the type + /// of interface-typed shader parameters. virtual SLANG_NO_THROW Result SLANG_MCALL setSpecializationArgs( ShaderOffset const& offset, const slang::SpecializationArg* args, GfxCount count) = 0; - virtual SLANG_NO_THROW Result SLANG_MCALL getCurrentVersion( - ITransientResourceHeap* transientHeap, - IShaderObject** outObject) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + getCurrentVersion(ITransientResourceHeap* transientHeap, IShaderObject** outObject) = 0; virtual SLANG_NO_THROW const void* SLANG_MCALL getRawData() = 0; virtual SLANG_NO_THROW Size SLANG_MCALL getSize() = 0; - /// Use the provided constant buffer instead of the internally created one. - virtual SLANG_NO_THROW Result SLANG_MCALL setConstantBufferOverride(IBufferResource* constantBuffer) = 0; + /// Use the provided constant buffer instead of the internally created one. + virtual SLANG_NO_THROW Result SLANG_MCALL + setConstantBufferOverride(IBufferResource* constantBuffer) = 0; inline ComPtr getObject(ShaderOffset const& offset) @@ -1172,9 +1232,12 @@ public: return entryPoint; } }; -#define SLANG_UUID_IShaderObject \ - { \ - 0xc1fa997e, 0x5ca2, 0x45ae, { 0x9b, 0xcb, 0xc4, 0x35, 0x9e, 0x85, 0x5, 0x85 } \ +#define SLANG_UUID_IShaderObject \ + { \ + 0xc1fa997e, 0x5ca2, 0x45ae, \ + { \ + 0x9b, 0xcb, 0xc4, 0x35, 0x9e, 0x85, 0x5, 0x85 \ + } \ } enum class StencilOp : uint8_t @@ -1210,23 +1273,23 @@ enum class FrontFaceMode : uint8_t struct DepthStencilOpDesc { - StencilOp stencilFailOp = StencilOp::Keep; - StencilOp stencilDepthFailOp = StencilOp::Keep; - StencilOp stencilPassOp = StencilOp::Keep; - ComparisonFunc stencilFunc = ComparisonFunc::Always; + StencilOp stencilFailOp = StencilOp::Keep; + StencilOp stencilDepthFailOp = StencilOp::Keep; + StencilOp stencilPassOp = StencilOp::Keep; + ComparisonFunc stencilFunc = ComparisonFunc::Always; }; struct DepthStencilDesc { - bool depthTestEnable = false; - bool depthWriteEnable = true; - ComparisonFunc depthFunc = ComparisonFunc::Less; + bool depthTestEnable = false; + bool depthWriteEnable = true; + ComparisonFunc depthFunc = ComparisonFunc::Less; - bool stencilEnable = false; - uint32_t stencilReadMask = 0xFFFFFFFF; - uint32_t stencilWriteMask = 0xFFFFFFFF; - DepthStencilOpDesc frontFace; - DepthStencilOpDesc backFace; + bool stencilEnable = false; + uint32_t stencilReadMask = 0xFFFFFFFF; + uint32_t stencilWriteMask = 0xFFFFFFFF; + DepthStencilOpDesc frontFace; + DepthStencilOpDesc backFace; uint32_t stencilRef = 0; // TODO: this should be removed }; @@ -1284,24 +1347,24 @@ enum class BlendFactor namespace RenderTargetWriteMask { - typedef uint8_t Type; - enum - { - EnableNone = 0, - EnableRed = 0x01, - EnableGreen = 0x02, - EnableBlue = 0x04, - EnableAlpha = 0x08, - EnableAll = 0x0F, - }; +typedef uint8_t Type; +enum +{ + EnableNone = 0, + EnableRed = 0x01, + EnableGreen = 0x02, + EnableBlue = 0x04, + EnableAlpha = 0x08, + EnableAll = 0x0F, }; +}; // namespace RenderTargetWriteMask typedef RenderTargetWriteMask::Type RenderTargetWriteMaskT; struct AspectBlendDesc { - BlendFactor srcFactor = BlendFactor::One; - BlendFactor dstFactor = BlendFactor::Zero; - BlendOp op = BlendOp::Add; + BlendFactor srcFactor = BlendFactor::One; + BlendFactor dstFactor = BlendFactor::Zero; + BlendOp op = BlendOp::Add; }; struct TargetBlendDesc @@ -1309,16 +1372,16 @@ struct TargetBlendDesc AspectBlendDesc color; AspectBlendDesc alpha; bool enableBlend = false; - LogicOp logicOp = LogicOp::NoOp; - RenderTargetWriteMaskT writeMask = RenderTargetWriteMask::EnableAll; + LogicOp logicOp = LogicOp::NoOp; + RenderTargetWriteMaskT writeMask = RenderTargetWriteMask::EnableAll; }; struct BlendDesc { - TargetBlendDesc targets[kMaxRenderTargetCount]; - GfxCount targetCount = 0; + TargetBlendDesc targets[kMaxRenderTargetCount]; + GfxCount targetCount = 0; - bool alphaToCoverageEnable = false; + bool alphaToCoverageEnable = false; }; class IFramebufferLayout : public ISlangUnknown @@ -1336,26 +1399,29 @@ public: TargetLayout* depthStencil = nullptr; }; }; -#define SLANG_UUID_IFramebufferLayout \ - { \ - 0xa838785, 0xc13a, 0x4832, { 0xad, 0x88, 0x64, 0x6, 0xb5, 0x4b, 0x5e, 0xba } \ +#define SLANG_UUID_IFramebufferLayout \ + { \ + 0xa838785, 0xc13a, 0x4832, \ + { \ + 0xad, 0x88, 0x64, 0x6, 0xb5, 0x4b, 0x5e, 0xba \ + } \ } struct GraphicsPipelineStateDesc { - IShaderProgram* program = nullptr; + IShaderProgram* program = nullptr; - IInputLayout* inputLayout = nullptr; + IInputLayout* inputLayout = nullptr; IFramebufferLayout* framebufferLayout = nullptr; - PrimitiveType primitiveType = PrimitiveType::Triangle; - DepthStencilDesc depthStencil; - RasterizerDesc rasterizer; - BlendDesc blend; + PrimitiveType primitiveType = PrimitiveType::Triangle; + DepthStencilDesc depthStencil; + RasterizerDesc rasterizer; + BlendDesc blend; }; struct ComputePipelineStateDesc { - IShaderProgram* program = nullptr; + IShaderProgram* program = nullptr; void* d3d12RootSignatureOverride = nullptr; }; @@ -1394,8 +1460,8 @@ public: // Specifies the bytes to overwrite into a record in the shader table. struct ShaderRecordOverwrite { - Offset offset; // Offset within the shader record. - Size size; // Number of bytes to overwrite. + Offset offset; // Offset within the shader record. + Size size; // Number of bytes to overwrite. uint8_t data[8]; // Content to overwrite. }; @@ -1420,9 +1486,12 @@ public: IShaderProgram* program; }; }; -#define SLANG_UUID_IShaderTable \ - { \ - 0xa721522c, 0xdf31, 0x4c2f, { 0xa5, 0xe7, 0x3b, 0xe0, 0x12, 0x4b, 0x31, 0x78 } \ +#define SLANG_UUID_IShaderTable \ + { \ + 0xa721522c, 0xdf31, 0x4c2f, \ + { \ + 0xa5, 0xe7, 0x3b, 0xe0, 0x12, 0x4b, 0x31, 0x78 \ + } \ } class IPipelineState : public ISlangUnknown @@ -1430,9 +1499,12 @@ class IPipelineState : public ISlangUnknown public: virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) = 0; }; -#define SLANG_UUID_IPipelineState \ - { \ - 0xca7e57d, 0x8a90, 0x44f3, { 0xbd, 0xb1, 0xfe, 0x9b, 0x35, 0x3f, 0x5a, 0x72 } \ +#define SLANG_UUID_IPipelineState \ + { \ + 0xca7e57d, 0x8a90, 0x44f3, \ + { \ + 0xbd, 0xb1, 0xfe, 0x9b, 0x35, 0x3f, 0x5a, 0x72 \ + } \ } @@ -1450,8 +1522,8 @@ struct Viewport float originY = 0.0f; float extentX = 0.0f; float extentY = 0.0f; - float minZ = 0.0f; - float maxZ = 1.0f; + float minZ = 0.0f; + float maxZ = 1.0f; }; class IFramebuffer : public ISlangUnknown @@ -1465,9 +1537,12 @@ public: IFramebufferLayout* layout; }; }; -#define SLANG_UUID_IFrameBuffer \ - { \ - 0xf0c0d9a, 0x4ef3, 0x4e18, { 0x9b, 0xa9, 0x34, 0x60, 0xea, 0x69, 0x87, 0x95 } \ +#define SLANG_UUID_IFrameBuffer \ + { \ + 0xf0c0d9a, 0x4ef3, 0x4e18, \ + { \ + 0x9b, 0xa9, 0x34, 0x60, 0xea, 0x69, 0x87, 0x95 \ + } \ } struct WindowHandle @@ -1509,7 +1584,8 @@ struct FaceMask { enum Enum { - Front = 1, Back = 2 + Front = 1, + Back = 2 }; }; @@ -1518,11 +1594,14 @@ class IRenderPassLayout : public ISlangUnknown public: enum class TargetLoadOp { - Load, Clear, DontCare + Load, + Clear, + DontCare }; enum class TargetStoreOp { - Store, DontCare + Store, + DontCare }; struct TargetAccessDesc { @@ -1541,9 +1620,12 @@ public: TargetAccessDesc* depthStencilAccess = nullptr; }; }; -#define SLANG_UUID_IRenderPassLayout \ - { \ - 0xdaab0b1a, 0xf45d, 0x4ae9, { 0xbf, 0x2c, 0xe0, 0xbb, 0x76, 0x7d, 0xfa, 0xd1 } \ +#define SLANG_UUID_IRenderPassLayout \ + { \ + 0xdaab0b1a, 0xf45d, 0x4ae9, \ + { \ + 0xbf, 0x2c, 0xe0, 0xbb, 0x76, 0x7d, 0xfa, 0xd1 \ + } \ } enum class QueryType @@ -1562,20 +1644,33 @@ public: QueryType type; GfxCount count; }; + public: - virtual SLANG_NO_THROW Result SLANG_MCALL getResult(GfxIndex queryIndex, GfxCount count, uint64_t* data) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + getResult(GfxIndex queryIndex, GfxCount count, uint64_t* data) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL reset() = 0; }; -#define SLANG_UUID_IQueryPool \ - { 0xc2cc3784, 0x12da, 0x480a, { 0xa8, 0x74, 0x8b, 0x31, 0x96, 0x1c, 0xa4, 0x36 } } +#define SLANG_UUID_IQueryPool \ + { \ + 0xc2cc3784, 0x12da, 0x480a, \ + { \ + 0xa8, 0x74, 0x8b, 0x31, 0x96, 0x1c, 0xa4, 0x36 \ + } \ + } class ICommandEncoder : public ISlangUnknown { - SLANG_COM_INTERFACE( 0x77ea6383, 0xbe3d, 0x40aa, { 0x8b, 0x45, 0xfd, 0xf0, 0xd7, 0x5b, 0xfa, 0x34 }); + SLANG_COM_INTERFACE( + 0x77ea6383, + 0xbe3d, + 0x40aa, + {0x8b, 0x45, 0xfd, 0xf0, 0xd7, 0x5b, 0xfa, 0x34}); + public: virtual SLANG_NO_THROW void SLANG_MCALL endEncoding() = 0; - virtual SLANG_NO_THROW void SLANG_MCALL writeTimestamp(IQueryPool* queryPool, GfxIndex queryIndex) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL + writeTimestamp(IQueryPool* queryPool, GfxIndex queryIndex) = 0; }; struct IndirectDispatchArguments @@ -1622,7 +1717,11 @@ struct ClearResourceViewFlags class IResourceCommandEncoder : public ICommandEncoder { // {F99A00E9-ED50-4088-8A0E-3B26755031EA} - SLANG_COM_INTERFACE(0xf99a00e9, 0xed50, 0x4088, { 0x8a, 0xe, 0x3b, 0x26, 0x75, 0x50, 0x31, 0xea }); + SLANG_COM_INTERFACE( + 0xf99a00e9, + 0xed50, + 0x4088, + {0x8a, 0xe, 0x3b, 0x26, 0x75, 0x50, 0x31, 0xea}); public: virtual SLANG_NO_THROW void SLANG_MCALL copyBuffer( @@ -1665,18 +1764,26 @@ public: ITextureResource::SubresourceData* subResourceData, GfxCount subResourceDataCount) = 0; virtual SLANG_NO_THROW void SLANG_MCALL - uploadBufferData(IBufferResource* dst, Offset offset, Size size, void* data) = 0; + uploadBufferData(IBufferResource* dst, Offset offset, Size size, void* data) = 0; virtual SLANG_NO_THROW void SLANG_MCALL textureBarrier( - GfxCount count, ITextureResource* const* textures, ResourceState src, ResourceState dst) = 0; + GfxCount count, + ITextureResource* const* textures, + ResourceState src, + ResourceState dst) = 0; virtual SLANG_NO_THROW void SLANG_MCALL textureSubresourceBarrier( ITextureResource* texture, SubresourceRange subresourceRange, ResourceState src, ResourceState dst) = 0; virtual SLANG_NO_THROW void SLANG_MCALL bufferBarrier( - GfxCount count, IBufferResource* const* buffers, ResourceState src, ResourceState dst) = 0; + GfxCount count, + IBufferResource* const* buffers, + ResourceState src, + ResourceState dst) = 0; virtual SLANG_NO_THROW void SLANG_MCALL clearResourceView( - IResourceView* view, ClearValue* clearValue, ClearResourceViewFlags::Enum flags) = 0; + IResourceView* view, + ClearValue* clearValue, + ClearResourceViewFlags::Enum flags) = 0; virtual SLANG_NO_THROW void SLANG_MCALL resolveResource( ITextureResource* source, ResourceState sourceState, @@ -1690,7 +1797,8 @@ public: GfxCount count, IBufferResource* buffer, Offset offset) = 0; - virtual SLANG_NO_THROW void SLANG_MCALL beginDebugEvent(const char* name, float rgbColor[3]) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL + beginDebugEvent(const char* name, float rgbColor[3]) = 0; virtual SLANG_NO_THROW void SLANG_MCALL endDebugEvent() = 0; inline void textureBarrier(ITextureResource* texture, ResourceState src, ResourceState dst) { @@ -1705,7 +1813,11 @@ public: class IRenderCommandEncoder : public IResourceCommandEncoder { // {7A8D56D0-53E6-4AD6-85F7-D14DC110FDCE} - SLANG_COM_INTERFACE(0x7a8d56d0, 0x53e6, 0x4ad6, { 0x85, 0xf7, 0xd1, 0x4d, 0xc1, 0x10, 0xfd, 0xce }) + SLANG_COM_INTERFACE( + 0x7a8d56d0, + 0x53e6, + 0x4ad6, + {0x85, 0xf7, 0xd1, 0x4d, 0xc1, 0x10, 0xfd, 0xce}) public: // Sets the current pipeline state. This method returns a transient shader object for // writing shader parameters. This shader object will not retain any resources or @@ -1713,7 +1825,7 @@ public: // resources or shader objects that is set into `outRootShaderObject` stays alive during // the execution of the command buffer. virtual SLANG_NO_THROW Result SLANG_MCALL - bindPipeline(IPipelineState* state, IShaderObject** outRootShaderObject) = 0; + bindPipeline(IPipelineState* state, IShaderObject** outRootShaderObject) = 0; inline IShaderObject* bindPipeline(IPipelineState* state) { IShaderObject* rootObject = nullptr; @@ -1723,12 +1835,12 @@ public: // Sets the current pipeline state along with a pre-created mutable root shader object. virtual SLANG_NO_THROW Result SLANG_MCALL - bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) = 0; + bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) = 0; - virtual SLANG_NO_THROW void - SLANG_MCALL setViewports(GfxCount count, const Viewport* viewports) = 0; - virtual SLANG_NO_THROW void - SLANG_MCALL setScissorRects(GfxCount count, const ScissorRect* scissors) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL + setViewports(GfxCount count, const Viewport* viewports) = 0; + virtual SLANG_NO_THROW void SLANG_MCALL + setScissorRects(GfxCount count, const ScissorRect* scissors) = 0; /// Sets the viewport, and sets the scissor rect to match the viewport. inline void setViewportAndScissor(Viewport const& viewport) @@ -1746,18 +1858,17 @@ public: GfxCount slotCount, IBufferResource* const* buffers, const Offset* offsets) = 0; - inline void setVertexBuffer( - GfxIndex slot, IBufferResource* buffer, Offset offset = 0) + inline void setVertexBuffer(GfxIndex slot, IBufferResource* buffer, Offset offset = 0) { setVertexBuffers(slot, 1, &buffer, &offset); } virtual SLANG_NO_THROW void SLANG_MCALL - setIndexBuffer(IBufferResource* buffer, Format indexFormat, Offset offset = 0) = 0; + setIndexBuffer(IBufferResource* buffer, Format indexFormat, Offset offset = 0) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL - draw(GfxCount vertexCount, GfxIndex startVertex = 0) = 0; + draw(GfxCount vertexCount, GfxIndex startVertex = 0) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL - drawIndexed(GfxCount indexCount, GfxIndex startIndex = 0, GfxIndex baseVertex = 0) = 0; + drawIndexed(GfxCount indexCount, GfxIndex startIndex = 0, GfxIndex baseVertex = 0) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL drawIndirect( GfxCount maxDrawCount, IBufferResource* argBuffer, @@ -1772,7 +1883,9 @@ public: Offset countOffset = 0) = 0; virtual SLANG_NO_THROW void SLANG_MCALL setStencilReference(uint32_t referenceValue) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL setSamplePositions( - GfxCount samplesPerPixel, GfxCount pixelCount, const SamplePosition* samplePositions) = 0; + GfxCount samplesPerPixel, + GfxCount pixelCount, + const SamplePosition* samplePositions) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL drawInstanced( GfxCount vertexCount, GfxCount instanceCount, @@ -1784,14 +1897,17 @@ public: GfxIndex startIndexLocation, GfxIndex baseVertexLocation, GfxIndex startInstanceLocation) = 0; - virtual SLANG_NO_THROW Result SLANG_MCALL - drawMeshTasks(int x, int y, int z) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL drawMeshTasks(int x, int y, int z) = 0; }; class IComputeCommandEncoder : public IResourceCommandEncoder { // {88AA9322-82F7-4FE6-A68A-29C7FE798737} - SLANG_COM_INTERFACE(0x88aa9322, 0x82f7, 0x4fe6, { 0xa6, 0x8a, 0x29, 0xc7, 0xfe, 0x79, 0x87, 0x37 }) + SLANG_COM_INTERFACE( + 0x88aa9322, + 0x82f7, + 0x4fe6, + {0xa6, 0x8a, 0x29, 0xc7, 0xfe, 0x79, 0x87, 0x37}) public: // Sets the current pipeline state. This method returns a transient shader object for @@ -1800,7 +1916,7 @@ public: // resources or shader objects that is set into `outRooShaderObject` stays alive during // the execution of the command buffer. virtual SLANG_NO_THROW Result SLANG_MCALL - bindPipeline(IPipelineState* state, IShaderObject** outRootShaderObject) = 0; + bindPipeline(IPipelineState* state, IShaderObject** outRootShaderObject) = 0; inline IShaderObject* bindPipeline(IPipelineState* state) { IShaderObject* rootObject = nullptr; @@ -1809,14 +1925,16 @@ public: } // Sets the current pipeline state along with a pre-created mutable root shader object. virtual SLANG_NO_THROW Result SLANG_MCALL - bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) = 0; + bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL dispatchCompute(int x, int y, int z) = 0; - virtual SLANG_NO_THROW Result SLANG_MCALL dispatchComputeIndirect(IBufferResource* cmdBuffer, Offset offset) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + dispatchComputeIndirect(IBufferResource* cmdBuffer, Offset offset) = 0; }; enum class AccelerationStructureCopyMode { - Clone, Compact + Clone, + Compact }; struct AccelerationStructureQueryDesc @@ -1830,7 +1948,11 @@ struct AccelerationStructureQueryDesc class IRayTracingCommandEncoder : public IResourceCommandEncoder { - SLANG_COM_INTERFACE(0x9a672b87, 0x5035, 0x45e3, { 0x96, 0x7c, 0x1f, 0x85, 0xcd, 0xb3, 0x63, 0x4f }) + SLANG_COM_INTERFACE( + 0x9a672b87, + 0x5035, + 0x45e3, + {0x96, 0x7c, 0x1f, 0x85, 0xcd, 0xb3, 0x63, 0x4f}) public: virtual SLANG_NO_THROW void SLANG_MCALL buildAccelerationStructure( const IAccelerationStructure::BuildDesc& desc, @@ -1846,18 +1968,19 @@ public: GfxCount queryCount, AccelerationStructureQueryDesc* queryDescs) = 0; virtual SLANG_NO_THROW void SLANG_MCALL - serializeAccelerationStructure(DeviceAddress dest, IAccelerationStructure* source) = 0; + serializeAccelerationStructure(DeviceAddress dest, IAccelerationStructure* source) = 0; virtual SLANG_NO_THROW void SLANG_MCALL - deserializeAccelerationStructure(IAccelerationStructure* dest, DeviceAddress source) = 0; + deserializeAccelerationStructure(IAccelerationStructure* dest, DeviceAddress source) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL - bindPipeline(IPipelineState* state, IShaderObject** outRootObject) = 0; + bindPipeline(IPipelineState* state, IShaderObject** outRootObject) = 0; // Sets the current pipeline state along with a pre-created mutable root shader object. virtual SLANG_NO_THROW Result SLANG_MCALL - bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) = 0; + bindPipelineWithRootObject(IPipelineState* state, IShaderObject* rootObject) = 0; /// Issues a dispatch command to start ray tracing workload with a ray tracing pipeline. - /// `rayGenShaderIndex` specifies the index into the shader table that identifies the ray generation shader. + /// `rayGenShaderIndex` specifies the index into the shader table that identifies the ray + /// generation shader. virtual SLANG_NO_THROW Result SLANG_MCALL dispatchRays( GfxIndex rayGenShaderIndex, IShaderTable* shaderTable, @@ -1878,8 +2001,9 @@ public: IRenderPassLayout* renderPass, IFramebuffer* framebuffer, IRenderCommandEncoder** outEncoder) = 0; - inline IRenderCommandEncoder* - encodeRenderCommands(IRenderPassLayout* renderPass, IFramebuffer* framebuffer) + inline IRenderCommandEncoder* encodeRenderCommands( + IRenderPassLayout* renderPass, + IFramebuffer* framebuffer) { IRenderCommandEncoder* result; encodeRenderCommands(renderPass, framebuffer, &result); @@ -1887,7 +2011,7 @@ public: } virtual SLANG_NO_THROW void SLANG_MCALL - encodeComputeCommands(IComputeCommandEncoder** outEncoder) = 0; + encodeComputeCommands(IComputeCommandEncoder** outEncoder) = 0; inline IComputeCommandEncoder* encodeComputeCommands() { IComputeCommandEncoder* result; @@ -1896,7 +2020,7 @@ public: } virtual SLANG_NO_THROW void SLANG_MCALL - encodeResourceCommands(IResourceCommandEncoder** outEncoder) = 0; + encodeResourceCommands(IResourceCommandEncoder** outEncoder) = 0; inline IResourceCommandEncoder* encodeResourceCommands() { IResourceCommandEncoder* result; @@ -1905,7 +2029,7 @@ public: } virtual SLANG_NO_THROW void SLANG_MCALL - encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) = 0; + encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) = 0; inline IRayTracingCommandEncoder* encodeRayTracingCommands() { IRayTracingCommandEncoder* result; @@ -1917,9 +2041,12 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL getNativeHandle(InteropHandle* outHandle) = 0; }; -#define SLANG_UUID_ICommandBuffer \ - { \ - 0x5d56063f, 0x91d4, 0x4723, { 0xa7, 0xa7, 0x7a, 0x15, 0xaf, 0x93, 0xeb, 0x48 } \ +#define SLANG_UUID_ICommandBuffer \ + { \ + 0x5d56063f, 0x91d4, 0x4723, \ + { \ + 0xa7, 0xa7, 0x7a, 0x15, 0xaf, 0x93, 0xeb, 0x48 \ + } \ } class ICommandBufferD3D12 : public ICommandBuffer @@ -1928,9 +2055,12 @@ public: virtual SLANG_NO_THROW void SLANG_MCALL invalidateDescriptorHeapBinding() = 0; virtual SLANG_NO_THROW void SLANG_MCALL ensureInternalDescriptorHeapsBound() = 0; }; -#define SLANG_UUID_ICommandBufferD3D12 \ - { \ - 0xd56b7616, 0x6c14, 0x4841, { 0x9d, 0x9c, 0x7b, 0x7f, 0xdb, 0x9f, 0xd9, 0xb8 } \ +#define SLANG_UUID_ICommandBufferD3D12 \ + { \ + 0xd56b7616, 0x6c14, 0x4841, \ + { \ + 0x9d, 0x9c, 0x7b, 0x7f, 0xdb, 0x9f, 0xd9, 0xb8 \ + } \ } class ICommandQueue : public ISlangUnknown @@ -1956,7 +2086,9 @@ public: IFence* fenceToSignal, uint64_t newFenceValue) = 0; inline void executeCommandBuffer( - ICommandBuffer* commandBuffer, IFence* fenceToSignal = nullptr, uint64_t newFenceValue = 0) + ICommandBuffer* commandBuffer, + IFence* fenceToSignal = nullptr, + uint64_t newFenceValue = 0) { executeCommandBuffers(1, &commandBuffer, fenceToSignal, newFenceValue); } @@ -1967,11 +2099,14 @@ public: /// Queues a device side wait for the given fences. virtual SLANG_NO_THROW Result SLANG_MCALL - waitForFenceValuesOnDevice(GfxCount fenceCount, IFence** fences, uint64_t* waitValues) = 0; + waitForFenceValuesOnDevice(GfxCount fenceCount, IFence** fences, uint64_t* waitValues) = 0; }; -#define SLANG_UUID_ICommandQueue \ - { \ - 0x14e2bed0, 0xad0, 0x4dc8, { 0xb3, 0x41, 0x6, 0x3f, 0xe7, 0x2d, 0xbf, 0xe } \ +#define SLANG_UUID_ICommandQueue \ + { \ + 0x14e2bed0, 0xad0, 0x4dc8, \ + { \ + 0xb3, 0x41, 0x6, 0x3f, 0xe7, 0x2d, 0xbf, 0xe \ + } \ } class ITransientResourceHeap : public ISlangUnknown @@ -2002,8 +2137,8 @@ public: // In most situations this method should be called at the beginning of each frame. virtual SLANG_NO_THROW Result SLANG_MCALL synchronizeAndReset() = 0; - // Must be called when the application has done using this heap to issue commands. In most situations - // this method should be called at the end of each frame. + // Must be called when the application has done using this heap to issue commands. In most + // situations this method should be called at the end of each frame. virtual SLANG_NO_THROW Result SLANG_MCALL finish() = 0; // Command buffers are one-time use. Once it is submitted to the queue via @@ -2012,7 +2147,7 @@ public: // that only one command buffer maybe recorded at a time. User must finish recording a command // buffer before creating another command buffer. virtual SLANG_NO_THROW Result SLANG_MCALL - createCommandBuffer(ICommandBuffer** outCommandBuffer) = 0; + createCommandBuffer(ICommandBuffer** outCommandBuffer) = 0; inline ComPtr createCommandBuffer() { ComPtr result; @@ -2020,9 +2155,12 @@ public: return result; } }; -#define SLANG_UUID_ITransientResourceHeap \ - { \ - 0xcd48bd29, 0xee72, 0x41b8, { 0xbc, 0xff, 0xa, 0x2b, 0x3a, 0xaa, 0x6d, 0xeb } \ +#define SLANG_UUID_ITransientResourceHeap \ + { \ + 0xcd48bd29, 0xee72, 0x41b8, \ + { \ + 0xbc, 0xff, 0xa, 0x2b, 0x3a, 0xaa, 0x6d, 0xeb \ + } \ } class ITransientResourceHeapD3D12 : public ISlangUnknown @@ -2030,7 +2168,8 @@ class ITransientResourceHeapD3D12 : public ISlangUnknown public: enum class DescriptorType { - ResourceView, Sampler + ResourceView, + Sampler }; virtual SLANG_NO_THROW Result SLANG_MCALL allocateTransientDescriptorTable( DescriptorType type, @@ -2038,9 +2177,12 @@ public: Offset& outDescriptorOffset, void** outD3DDescriptorHeapHandle) = 0; }; -#define SLANG_UUID_ITransientResourceHeapD3D12 \ - { \ - 0x9bc6a8bc, 0x5f7a, 0x454a, { 0x93, 0xef, 0x3b, 0x10, 0x5b, 0xb7, 0x63, 0x7e } \ +#define SLANG_UUID_ITransientResourceHeapD3D12 \ + { \ + 0x9bc6a8bc, 0x5f7a, 0x454a, \ + { \ + 0x93, 0xef, 0x3b, 0x10, 0x5b, 0xb7, 0x63, 0x7e \ + } \ } class ISwapchain : public ISlangUnknown @@ -2058,7 +2200,7 @@ public: /// Returns the back buffer image at `index`. virtual SLANG_NO_THROW Result SLANG_MCALL - getImage(GfxIndex index, ITextureResource** outResource) = 0; + getImage(GfxIndex index, ITextureResource** outResource) = 0; /// Present the next image in the swapchain. virtual SLANG_NO_THROW Result SLANG_MCALL present() = 0; @@ -2077,9 +2219,12 @@ public: // Toggle full screen mode. virtual SLANG_NO_THROW Result SLANG_MCALL setFullScreenMode(bool mode) = 0; }; -#define SLANG_UUID_ISwapchain \ - { \ - 0xbe91ba6c, 0x784, 0x4308, { 0xa1, 0x0, 0x19, 0xc3, 0x66, 0x83, 0x44, 0xb2 } \ +#define SLANG_UUID_ISwapchain \ + { \ + 0xbe91ba6c, 0x784, 0x4308, \ + { \ + 0xa1, 0x0, 0x19, 0xc3, 0x66, 0x83, 0x44, 0xb2 \ + } \ } struct AdapterLUID @@ -2093,10 +2238,7 @@ struct AdapterLUID return false; return true; } - bool operator!=(const AdapterLUID& other) const - { - return !this->operator==(other); - } + bool operator!=(const AdapterLUID& other) const { return !this->operator==(other); } }; struct AdapterInfo @@ -2107,7 +2249,8 @@ struct AdapterInfo // Unique identifier for the vendor (only available for D3D and Vulkan). uint32_t vendorID; - // Unique identifier for the physical device among devices from the vendor (only available for D3D and Vulkan) + // Unique identifier for the physical device among devices from the vendor (only available for + // D3D and Vulkan) uint32_t deviceID; // Logically unique identifier of the adapter. @@ -2117,7 +2260,10 @@ struct AdapterInfo class AdapterList { public: - AdapterList(ISlangBlob* blob) : m_blob(blob) {} + AdapterList(ISlangBlob* blob) + : m_blob(blob) + { + } const AdapterInfo* getAdapters() const { @@ -2199,17 +2345,21 @@ struct DeviceInfo enum class DebugMessageType { - Info, Warning, Error + Info, + Warning, + Error }; enum class DebugMessageSource { - Layer, Driver, Slang + Layer, + Driver, + Slang }; class IDebugCallback { public: virtual SLANG_NO_THROW void SLANG_MCALL - handleMessage(DebugMessageType type, DebugMessageSource source, const char* message) = 0; + handleMessage(DebugMessageType type, DebugMessageSource source, const char* message) = 0; }; class IDevice : public ISlangUnknown @@ -2217,21 +2367,23 @@ class IDevice : public ISlangUnknown public: struct SlangDesc { - slang::IGlobalSession* slangGlobalSession = nullptr; // (optional) A slang global session object. If null will create automatically. + slang::IGlobalSession* slangGlobalSession = + nullptr; // (optional) A slang global session object. If null will create automatically. SlangMatrixLayoutMode defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_ROW_MAJOR; char const* const* searchPaths = nullptr; - GfxCount searchPathCount = 0; + GfxCount searchPathCount = 0; slang::PreprocessorMacroDesc const* preprocessorMacros = nullptr; - GfxCount preprocessorMacroCount = 0; + GfxCount preprocessorMacroCount = 0; - const char* targetProfile = nullptr; // (optional) Target shader profile. If null this will be set to platform dependent default. + const char* targetProfile = nullptr; // (optional) Target shader profile. If null this will + // be set to platform dependent default. SlangFloatingPointMode floatingPointMode = SLANG_FLOATING_POINT_MODE_DEFAULT; SlangOptimizationLevel optimizationLevel = SLANG_OPTIMIZATION_LEVEL_DEFAULT; SlangTargetFlags targetFlags = kDefaultTargetFlags; - SlangLineDirectiveMode lineDirectiveMode = SLANG_LINE_DIRECTIVE_MODE_DEFAULT;\ + SlangLineDirectiveMode lineDirectiveMode = SLANG_LINE_DIRECTIVE_MODE_DEFAULT; }; struct ShaderCacheDesc @@ -2251,9 +2403,10 @@ public: { // The underlying API/Platform of the device. DeviceType deviceType = DeviceType::Default; - // The device's handles (if they exist) and their associated API. For D3D12, this contains a single InteropHandle - // for the ID3D12Device. For Vulkan, the first InteropHandle is the VkInstance, the second is the VkPhysicalDevice, - // and the third is the VkDevice. For CUDA, this only contains a single value for the CUDADevice. + // The device's handles (if they exist) and their associated API. For D3D12, this contains a + // single InteropHandle for the ID3D12Device. For Vulkan, the first InteropHandle is the + // VkInstance, the second is the VkPhysicalDevice, and the third is the VkDevice. For CUDA, + // this only contains a single value for the CUDADevice. InteropHandles existingDeviceHandles; // LUID of the adapter to use. Use getGfxAdapters() to get a list of available adapters. const AdapterLUID* adapterLUID = nullptr; @@ -2274,16 +2427,20 @@ public: void** extendedDescs = nullptr; }; - virtual SLANG_NO_THROW Result SLANG_MCALL getNativeDeviceHandles(InteropHandles* outHandles) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + getNativeDeviceHandles(InteropHandles* outHandles) = 0; virtual SLANG_NO_THROW bool SLANG_MCALL hasFeature(const char* feature) = 0; - /// Returns a list of features supported by the renderer. - virtual SLANG_NO_THROW Result SLANG_MCALL getFeatures(const char** outFeatures, Size bufferSize, GfxCount* outFeatureCount) = 0; + /// Returns a list of features supported by the renderer. + virtual SLANG_NO_THROW Result SLANG_MCALL + getFeatures(const char** outFeatures, Size bufferSize, GfxCount* outFeatureCount) = 0; - virtual SLANG_NO_THROW Result SLANG_MCALL getFormatSupportedResourceStates(Format format, ResourceStateSet* outStates) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + getFormatSupportedResourceStates(Format format, ResourceStateSet* outStates) = 0; - virtual SLANG_NO_THROW Result SLANG_MCALL getSlangSession(slang::ISession** outSlangSession) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + getSlangSession(slang::ISession** outSlangSession) = 0; inline ComPtr getSlangSession() { @@ -2303,26 +2460,27 @@ public: return result; } - /// Create a texture resource. - /// - /// If `initData` is non-null, then it must point to an array of - /// `ITextureResource::SubresourceData` with one element for each - /// subresource of the texture being created. - /// - /// The number of subresources in a texture is: - /// - /// effectiveElementCount * mipLevelCount - /// - /// where the effective element count is computed as: - /// - /// effectiveElementCount = (isArray ? arrayElementCount : 1) * (isCube ? 6 : 1); - /// + /// Create a texture resource. + /// + /// If `initData` is non-null, then it must point to an array of + /// `ITextureResource::SubresourceData` with one element for each + /// subresource of the texture being created. + /// + /// The number of subresources in a texture is: + /// + /// effectiveElementCount * mipLevelCount + /// + /// where the effective element count is computed as: + /// + /// effectiveElementCount = (isArray ? arrayElementCount : 1) * (isCube ? 6 : 1); + /// virtual SLANG_NO_THROW Result SLANG_MCALL createTextureResource( const ITextureResource::Desc& desc, const ITextureResource::SubresourceData* initData, ITextureResource** outResource) = 0; - /// Create a texture resource. initData holds the initialize data to set the contents of the texture when constructed. + /// Create a texture resource. initData holds the initialize data to set the contents of the + /// texture when constructed. inline SLANG_NO_THROW ComPtr createTextureResource( const ITextureResource::Desc& desc, const ITextureResource::SubresourceData* initData = nullptr) @@ -2343,7 +2501,7 @@ public: const Size size, ITextureResource** outResource) = 0; - /// Create a buffer resource + /// Create a buffer resource virtual SLANG_NO_THROW Result SLANG_MCALL createBufferResource( const IBufferResource::Desc& desc, const void* initData, @@ -2369,7 +2527,7 @@ public: IBufferResource** outResource) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL - createSamplerState(ISamplerState::Desc const& desc, ISamplerState** outSampler) = 0; + createSamplerState(ISamplerState::Desc const& desc, ISamplerState** outSampler) = 0; inline ComPtr createSamplerState(ISamplerState::Desc const& desc) { @@ -2379,9 +2537,13 @@ public: } virtual SLANG_NO_THROW Result SLANG_MCALL createTextureView( - ITextureResource* texture, IResourceView::Desc const& desc, IResourceView** outView) = 0; + ITextureResource* texture, + IResourceView::Desc const& desc, + IResourceView** outView) = 0; - inline ComPtr createTextureView(ITextureResource* texture, IResourceView::Desc const& desc) + inline ComPtr createTextureView( + ITextureResource* texture, + IResourceView::Desc const& desc) { ComPtr view; SLANG_RETURN_NULL_ON_FAIL(createTextureView(texture, desc, view.writeRef())); @@ -2395,15 +2557,18 @@ public: IResourceView** outView) = 0; inline ComPtr createBufferView( - IBufferResource* buffer, IBufferResource* counterBuffer, IResourceView::Desc const& desc) + IBufferResource* buffer, + IBufferResource* counterBuffer, + IResourceView::Desc const& desc) { ComPtr view; SLANG_RETURN_NULL_ON_FAIL(createBufferView(buffer, counterBuffer, desc, view.writeRef())); return view; } - virtual SLANG_NO_THROW Result SLANG_MCALL - createFramebufferLayout(IFramebufferLayout::Desc const& desc, IFramebufferLayout** outFrameBuffer) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL createFramebufferLayout( + IFramebufferLayout::Desc const& desc, + IFramebufferLayout** outFrameBuffer) = 0; inline ComPtr createFramebufferLayout(IFramebufferLayout::Desc const& desc) { ComPtr fb; @@ -2412,7 +2577,7 @@ public: } virtual SLANG_NO_THROW Result SLANG_MCALL - createFramebuffer(IFramebuffer::Desc const& desc, IFramebuffer** outFrameBuffer) = 0; + createFramebuffer(IFramebuffer::Desc const& desc, IFramebuffer** outFrameBuffer) = 0; inline ComPtr createFramebuffer(IFramebuffer::Desc const& desc) { ComPtr fb; @@ -2431,7 +2596,9 @@ public: } virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain( - ISwapchain::Desc const& desc, WindowHandle window, ISwapchain** outSwapchain) = 0; + ISwapchain::Desc const& desc, + WindowHandle window, + ISwapchain** outSwapchain) = 0; inline ComPtr createSwapchain(ISwapchain::Desc const& desc, WindowHandle window) { ComPtr swapchain; @@ -2439,8 +2606,8 @@ public: return swapchain; } - virtual SLANG_NO_THROW Result SLANG_MCALL createInputLayout( - IInputLayout::Desc const& desc, IInputLayout** outLayout) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + createInputLayout(IInputLayout::Desc const& desc, IInputLayout** outLayout) = 0; inline ComPtr createInputLayout(IInputLayout::Desc const& desc) { @@ -2449,9 +2616,13 @@ public: return layout; } - inline Result createInputLayout(Size vertexSize, InputElementDesc const* inputElements, GfxCount inputElementCount, IInputLayout** outLayout) + inline Result createInputLayout( + Size vertexSize, + InputElementDesc const* inputElements, + GfxCount inputElementCount, + IInputLayout** outLayout) { - VertexStreamDesc streamDesc = { vertexSize, InputSlotClass::PerVertex, 0 }; + VertexStreamDesc streamDesc = {vertexSize, InputSlotClass::PerVertex, 0}; IInputLayout::Desc inputLayoutDesc = {}; inputLayoutDesc.inputElementCount = inputElementCount; @@ -2461,15 +2632,19 @@ public: return createInputLayout(inputLayoutDesc, outLayout); } - inline ComPtr createInputLayout(Size vertexSize, InputElementDesc const* inputElements, GfxCount inputElementCount) + inline ComPtr createInputLayout( + Size vertexSize, + InputElementDesc const* inputElements, + GfxCount inputElementCount) { ComPtr layout; - SLANG_RETURN_NULL_ON_FAIL(createInputLayout(vertexSize, inputElements, inputElementCount, layout.writeRef())); + SLANG_RETURN_NULL_ON_FAIL( + createInputLayout(vertexSize, inputElements, inputElementCount, layout.writeRef())); return layout; } virtual SLANG_NO_THROW Result SLANG_MCALL - createCommandQueue(const ICommandQueue::Desc& desc, ICommandQueue** outQueue) = 0; + createCommandQueue(const ICommandQueue::Desc& desc, ICommandQueue** outQueue) = 0; inline ComPtr createCommandQueue(const ICommandQueue::Desc& desc) { ComPtr queue; @@ -2485,7 +2660,8 @@ public: inline ComPtr createShaderObject(slang::TypeReflection* type) { ComPtr object; - SLANG_RETURN_NULL_ON_FAIL(createShaderObject(type, ShaderObjectContainerType::None, object.writeRef())); + SLANG_RETURN_NULL_ON_FAIL( + createShaderObject(type, ShaderObjectContainerType::None, object.writeRef())); return object; } @@ -2495,17 +2671,18 @@ public: IShaderObject** outObject) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL createShaderObjectFromTypeLayout( - slang::TypeLayoutReflection* typeLayout, IShaderObject** outObject) = 0; + slang::TypeLayoutReflection* typeLayout, + IShaderObject** outObject) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL createMutableShaderObjectFromTypeLayout( - slang::TypeLayoutReflection* typeLayout, IShaderObject** outObject) = 0; - - virtual SLANG_NO_THROW Result SLANG_MCALL createMutableRootShaderObject( - IShaderProgram* program, + slang::TypeLayoutReflection* typeLayout, IShaderObject** outObject) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL - createShaderTable(const IShaderTable::Desc& desc, IShaderTable** outTable) = 0; + createMutableRootShaderObject(IShaderProgram* program, IShaderObject** outObject) = 0; + + virtual SLANG_NO_THROW Result SLANG_MCALL + createShaderTable(const IShaderTable::Desc& desc, IShaderTable** outTable) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL createProgram( const IShaderProgram::Desc& desc, @@ -2525,23 +2702,20 @@ public: ISlangBlob** outDiagnosticBlob = nullptr) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL createGraphicsPipelineState( - const GraphicsPipelineStateDesc& desc, - IPipelineState** outState) = 0; + const GraphicsPipelineStateDesc& desc, + IPipelineState** outState) = 0; - inline ComPtr createGraphicsPipelineState( - const GraphicsPipelineStateDesc& desc) + inline ComPtr createGraphicsPipelineState(const GraphicsPipelineStateDesc& desc) { ComPtr state; SLANG_RETURN_NULL_ON_FAIL(createGraphicsPipelineState(desc, state.writeRef())); return state; } - virtual SLANG_NO_THROW Result SLANG_MCALL createComputePipelineState( - const ComputePipelineStateDesc& desc, - IPipelineState** outState) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + createComputePipelineState(const ComputePipelineStateDesc& desc, IPipelineState** outState) = 0; - inline ComPtr createComputePipelineState( - const ComputePipelineStateDesc& desc) + inline ComPtr createComputePipelineState(const ComputePipelineStateDesc& desc) { ComPtr state; SLANG_RETURN_NULL_ON_FAIL(createComputePipelineState(desc, state.writeRef())); @@ -2549,9 +2723,10 @@ public: } virtual SLANG_NO_THROW Result SLANG_MCALL createRayTracingPipelineState( - const RayTracingPipelineStateDesc& desc, IPipelineState** outState) = 0; + const RayTracingPipelineStateDesc& desc, + IPipelineState** outState) = 0; - /// Read back texture resource and stores the result in `outBlob`. + /// Read back texture resource and stores the result in `outBlob`. virtual SLANG_NO_THROW SlangResult SLANG_MCALL readTextureResource( ITextureResource* resource, ResourceState state, @@ -2559,17 +2734,14 @@ public: Size* outRowPitch, Size* outPixelSize) = 0; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL readBufferResource( - IBufferResource* buffer, - Offset offset, - Size size, - ISlangBlob** outBlob) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + readBufferResource(IBufferResource* buffer, Offset offset, Size size, ISlangBlob** outBlob) = 0; - /// Get the type of this renderer + /// Get the type of this renderer virtual SLANG_NO_THROW const DeviceInfo& SLANG_MCALL getDeviceInfo() const = 0; - virtual SLANG_NO_THROW Result SLANG_MCALL createQueryPool( - const IQueryPool::Desc& desc, IQueryPool** outPool) = 0; + virtual SLANG_NO_THROW Result SLANG_MCALL + createQueryPool(const IQueryPool::Desc& desc, IQueryPool** outPool) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL getAccelerationStructurePrebuildInfo( @@ -2581,7 +2753,7 @@ public: IAccelerationStructure** outView) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL - createFence(const IFence::Desc& desc, IFence** outFence) = 0; + createFence(const IFence::Desc& desc, IFence** outFence) = 0; /// Wait on the host for the fences to signals. /// `timeout` is in nanoseconds, can be set to `kTimeoutInfinite`. @@ -2593,7 +2765,9 @@ public: uint64_t timeout) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL getTextureAllocationInfo( - const ITextureResource::Desc& desc, Size* outSize, Size* outAlignment) = 0; + const ITextureResource::Desc& desc, + Size* outSize, + Size* outAlignment) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL getTextureRowAlignment(Size* outAlignment) = 0; @@ -2610,9 +2784,12 @@ public: IShaderObject** outObject) = 0; }; -#define SLANG_UUID_IDevice \ - { \ - 0x715bdf26, 0x5135, 0x11eb, { 0xAE, 0x93, 0x02, 0x42, 0xAC, 0x13, 0x00, 0x02 } \ +#define SLANG_UUID_IDevice \ + { \ + 0x715bdf26, 0x5135, 0x11eb, \ + { \ + 0xAE, 0x93, 0x02, 0x42, 0xAC, 0x13, 0x00, 0x02 \ + } \ } struct ShaderCacheStats @@ -2634,9 +2811,12 @@ public: virtual SLANG_NO_THROW Result SLANG_MCALL resetShaderCacheStats() = 0; }; -#define SLANG_UUID_IShaderCache \ - { \ - 0x8eccc8ec, 0x5c04, 0x4a51, { 0x99, 0x75, 0x13, 0xf8, 0xfe, 0xa1, 0x59, 0xf3 } \ +#define SLANG_UUID_IShaderCache \ + { \ + 0x8eccc8ec, 0x5c04, 0x4a51, \ + { \ + 0x99, 0x75, 0x13, 0xf8, 0xfe, 0xa1, 0x59, 0xf3 \ + } \ } class IPipelineCreationAPIDispatcher : public ISlangUnknown @@ -2658,18 +2838,24 @@ public: void* pipelineDesc, void** outPipelineState) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL - beforeCreateRayTracingState(IDevice* device, slang::IComponentType* program) = 0; + beforeCreateRayTracingState(IDevice* device, slang::IComponentType* program) = 0; virtual SLANG_NO_THROW Result SLANG_MCALL - afterCreateRayTracingState(IDevice* device, slang::IComponentType* program) = 0; + afterCreateRayTracingState(IDevice* device, slang::IComponentType* program) = 0; }; -#define SLANG_UUID_IPipelineCreationAPIDispatcher \ - { \ - 0xc3d5f782, 0xeae1, 0x4da6, { 0xab, 0x40, 0x75, 0x32, 0x31, 0x2, 0xb7, 0xdc } \ +#define SLANG_UUID_IPipelineCreationAPIDispatcher \ + { \ + 0xc3d5f782, 0xeae1, 0x4da6, \ + { \ + 0xab, 0x40, 0x75, 0x32, 0x31, 0x2, 0xb7, 0xdc \ + } \ } -#define SLANG_UUID_IVulkanPipelineCreationAPIDispatcher \ - { \ - 0x4fcf1274, 0x8752, 0x4743, { 0xb3, 0x51, 0x47, 0xcb, 0x83, 0x71, 0xef, 0x99 } \ +#define SLANG_UUID_IVulkanPipelineCreationAPIDispatcher \ + { \ + 0x4fcf1274, 0x8752, 0x4743, \ + { \ + 0xb3, 0x51, 0x47, 0xcb, 0x83, 0x71, 0xef, 0x99 \ + } \ } // Global public functions @@ -2686,11 +2872,12 @@ extern "C" SLANG_GFX_API SlangResult SLANG_MCALL gfxGetFormatInfo(Format format, FormatInfo* outInfo); /// Gets a list of available adapters for a given device type - SLANG_GFX_API SlangResult SLANG_MCALL gfxGetAdapters(DeviceType type, ISlangBlob** outAdaptersBlob); + SLANG_GFX_API SlangResult SLANG_MCALL + gfxGetAdapters(DeviceType type, ISlangBlob** outAdaptersBlob); /// Given a type returns a function that can construct it, or nullptr if there isn't one SLANG_GFX_API SlangResult SLANG_MCALL - gfxCreateDevice(const IDevice::Desc* desc, IDevice** outDevice); + gfxCreateDevice(const IDevice::Desc* desc, IDevice** outDevice); /// Reports current set of live objects in gfx. /// Currently this only calls D3D's ReportLiveObjects. @@ -2699,10 +2886,10 @@ extern "C" /// Sets a callback for receiving debug messages. /// The layer does not hold a strong reference to the callback object. /// The user is responsible for holding the callback object alive. - SLANG_GFX_API SlangResult SLANG_MCALL - gfxSetDebugCallback(IDebugCallback* callback); + SLANG_GFX_API SlangResult SLANG_MCALL gfxSetDebugCallback(IDebugCallback* callback); - /// Enables debug layer. The debug layer will check all `gfx` calls and verify that uses are valid. + /// Enables debug layer. The debug layer will check all `gfx` calls and verify that uses are + /// valid. SLANG_GFX_API void SLANG_MCALL gfxEnableDebugLayer(); SLANG_GFX_API const char* SLANG_MCALL gfxGetDeviceTypeName(DeviceType type); @@ -2741,11 +2928,12 @@ struct SlangSessionExtendedDesc slang::CompilerOptionEntry* compilerOptionEntries = nullptr; }; -/// Whether to enable ray tracing validation (currently only Vulkan - D3D requires app layer to use NVAPI) +/// Whether to enable ray tracing validation (currently only Vulkan - D3D requires app layer to use +/// NVAPI) struct RayTracingValidationDesc { StructType structType = StructType::RayTracingValidationDesc; bool enableRaytracingValidation = false; }; -} +} // namespace gfx diff --git a/include/slang-image-format-defs.h b/include/slang-image-format-defs.h index 410c73339..0f7c7cec3 100644 --- a/include/slang-image-format-defs.h +++ b/include/slang-image-format-defs.h @@ -1,49 +1,49 @@ // slang-image-format-defs.h #ifndef SLANG_FORMAT -#error Must define SLANG_FORMAT macro before including image-format-defs.h + #error Must define SLANG_FORMAT macro before including image-format-defs.h #endif -SLANG_FORMAT(unknown, (NONE, 0, 0)) -SLANG_FORMAT(rgba32f, (FLOAT32, 4, sizeof(float) * 4)) -SLANG_FORMAT(rgba16f, (FLOAT16, 4, sizeof(uint16_t) * 4)) -SLANG_FORMAT(rg32f, (FLOAT32, 2, sizeof(float) * 2)) -SLANG_FORMAT(rg16f, (FLOAT16, 2, sizeof(uint16_t) * 2)) -SLANG_FORMAT(r11f_g11f_b10f, (NONE, 3, sizeof(uint32_t))) -SLANG_FORMAT(r32f, (FLOAT32, 1, sizeof(float))) -SLANG_FORMAT(r16f, (FLOAT16, 1, sizeof(uint16_t))) -SLANG_FORMAT(rgba16, (UINT16, 4, sizeof(uint16_t) * 4)) -SLANG_FORMAT(rgb10_a2, (NONE, 4, sizeof(uint32_t))) -SLANG_FORMAT(rgba8, (UINT8, 4, sizeof(uint32_t))) -SLANG_FORMAT(rg16, (UINT16, 2, sizeof(uint16_t) * 2 )) -SLANG_FORMAT(rg8, (UINT8, 2, sizeof(char) * 2)) -SLANG_FORMAT(r16, (UINT16, 1, sizeof(uint16_t))) -SLANG_FORMAT(r8, (UINT8, 1, sizeof(uint8_t))) -SLANG_FORMAT(rgba16_snorm, (UINT16, 4, sizeof(uint16_t) * 4)) -SLANG_FORMAT(rgba8_snorm, (UINT8, 4, sizeof(uint8_t) * 4)) -SLANG_FORMAT(rg16_snorm, (UINT16, 2, sizeof(uint16_t) * 2)) -SLANG_FORMAT(rg8_snorm, (UINT8, 2, sizeof(uint8_t) * 2)) -SLANG_FORMAT(r16_snorm, (UINT16, 1, sizeof(uint16_t))) -SLANG_FORMAT(r8_snorm, (UINT8, 1, sizeof(uint8_t))) -SLANG_FORMAT(rgba32i, (INT32, 4, sizeof(int32_t) * 4)) -SLANG_FORMAT(rgba16i, (INT16, 4, sizeof(int16_t) * 4)) -SLANG_FORMAT(rgba8i, (INT8, 4, sizeof(int8_t) * 4)) -SLANG_FORMAT(rg32i, (INT32, 2, sizeof(int32_t) * 2)) -SLANG_FORMAT(rg16i, (INT16, 2, sizeof(int16_t) * 2)) -SLANG_FORMAT(rg8i, (INT8, 2, sizeof(int8_t) * 2)) -SLANG_FORMAT(r32i, (INT32, 1, sizeof(int32_t))) -SLANG_FORMAT(r16i, (INT16, 1, sizeof(int16_t))) -SLANG_FORMAT(r8i, (INT8, 1, sizeof(int8_t))) -SLANG_FORMAT(rgba32ui, (UINT32, 4, sizeof(uint32_t) * 4)) -SLANG_FORMAT(rgba16ui, (UINT16, 4, sizeof(uint16_t) * 4)) -SLANG_FORMAT(rgb10_a2ui, (NONE, 4, sizeof(uint32_t))) -SLANG_FORMAT(rgba8ui, (UINT8, 4, sizeof(uint8_t) * 4)) -SLANG_FORMAT(rg32ui, (UINT32, 2, sizeof(uint32_t) * 2)) -SLANG_FORMAT(rg16ui, (UINT16, 2, sizeof(uint16_t) * 2)) -SLANG_FORMAT(rg8ui, (UINT8, 2, sizeof(uint8_t) * 2)) -SLANG_FORMAT(r32ui, (UINT32, 1, sizeof(uint32_t))) -SLANG_FORMAT(r16ui, (UINT16, 1, sizeof(uint16_t))) -SLANG_FORMAT(r8ui, (UINT8, 1, sizeof(uint8_t))) -SLANG_FORMAT(r64ui, (UINT64, 1, sizeof(uint64_t))) -SLANG_FORMAT(r64i, (INT64, 1, sizeof(int64_t))) +SLANG_FORMAT(unknown, (NONE, 0, 0)) +SLANG_FORMAT(rgba32f, (FLOAT32, 4, sizeof(float) * 4)) +SLANG_FORMAT(rgba16f, (FLOAT16, 4, sizeof(uint16_t) * 4)) +SLANG_FORMAT(rg32f, (FLOAT32, 2, sizeof(float) * 2)) +SLANG_FORMAT(rg16f, (FLOAT16, 2, sizeof(uint16_t) * 2)) +SLANG_FORMAT(r11f_g11f_b10f, (NONE, 3, sizeof(uint32_t))) +SLANG_FORMAT(r32f, (FLOAT32, 1, sizeof(float))) +SLANG_FORMAT(r16f, (FLOAT16, 1, sizeof(uint16_t))) +SLANG_FORMAT(rgba16, (UINT16, 4, sizeof(uint16_t) * 4)) +SLANG_FORMAT(rgb10_a2, (NONE, 4, sizeof(uint32_t))) +SLANG_FORMAT(rgba8, (UINT8, 4, sizeof(uint32_t))) +SLANG_FORMAT(rg16, (UINT16, 2, sizeof(uint16_t) * 2)) +SLANG_FORMAT(rg8, (UINT8, 2, sizeof(char) * 2)) +SLANG_FORMAT(r16, (UINT16, 1, sizeof(uint16_t))) +SLANG_FORMAT(r8, (UINT8, 1, sizeof(uint8_t))) +SLANG_FORMAT(rgba16_snorm, (UINT16, 4, sizeof(uint16_t) * 4)) +SLANG_FORMAT(rgba8_snorm, (UINT8, 4, sizeof(uint8_t) * 4)) +SLANG_FORMAT(rg16_snorm, (UINT16, 2, sizeof(uint16_t) * 2)) +SLANG_FORMAT(rg8_snorm, (UINT8, 2, sizeof(uint8_t) * 2)) +SLANG_FORMAT(r16_snorm, (UINT16, 1, sizeof(uint16_t))) +SLANG_FORMAT(r8_snorm, (UINT8, 1, sizeof(uint8_t))) +SLANG_FORMAT(rgba32i, (INT32, 4, sizeof(int32_t) * 4)) +SLANG_FORMAT(rgba16i, (INT16, 4, sizeof(int16_t) * 4)) +SLANG_FORMAT(rgba8i, (INT8, 4, sizeof(int8_t) * 4)) +SLANG_FORMAT(rg32i, (INT32, 2, sizeof(int32_t) * 2)) +SLANG_FORMAT(rg16i, (INT16, 2, sizeof(int16_t) * 2)) +SLANG_FORMAT(rg8i, (INT8, 2, sizeof(int8_t) * 2)) +SLANG_FORMAT(r32i, (INT32, 1, sizeof(int32_t))) +SLANG_FORMAT(r16i, (INT16, 1, sizeof(int16_t))) +SLANG_FORMAT(r8i, (INT8, 1, sizeof(int8_t))) +SLANG_FORMAT(rgba32ui, (UINT32, 4, sizeof(uint32_t) * 4)) +SLANG_FORMAT(rgba16ui, (UINT16, 4, sizeof(uint16_t) * 4)) +SLANG_FORMAT(rgb10_a2ui, (NONE, 4, sizeof(uint32_t))) +SLANG_FORMAT(rgba8ui, (UINT8, 4, sizeof(uint8_t) * 4)) +SLANG_FORMAT(rg32ui, (UINT32, 2, sizeof(uint32_t) * 2)) +SLANG_FORMAT(rg16ui, (UINT16, 2, sizeof(uint16_t) * 2)) +SLANG_FORMAT(rg8ui, (UINT8, 2, sizeof(uint8_t) * 2)) +SLANG_FORMAT(r32ui, (UINT32, 1, sizeof(uint32_t))) +SLANG_FORMAT(r16ui, (UINT16, 1, sizeof(uint16_t))) +SLANG_FORMAT(r8ui, (UINT8, 1, sizeof(uint8_t))) +SLANG_FORMAT(r64ui, (UINT64, 1, sizeof(uint64_t))) +SLANG_FORMAT(r64i, (INT64, 1, sizeof(int64_t))) #undef SLANG_FORMAT diff --git a/include/slang.h b/include/slang.h index c466cd3b6..c40ef1c7b 100644 --- a/include/slang.h +++ b/include/slang.h @@ -17,55 +17,55 @@ used later in the file. Most applications should not need to touch this section. */ #ifndef SLANG_COMPILER -# define SLANG_COMPILER + #define SLANG_COMPILER -/* -Compiler defines, see http://sourceforge.net/p/predef/wiki/Compilers/ -NOTE that SLANG_VC holds the compiler version - not just 1 or 0 -*/ -# if defined(_MSC_VER) -# if _MSC_VER >= 1900 -# define SLANG_VC 14 -# elif _MSC_VER >= 1800 -# define SLANG_VC 12 -# elif _MSC_VER >= 1700 -# define SLANG_VC 11 -# elif _MSC_VER >= 1600 -# define SLANG_VC 10 -# elif _MSC_VER >= 1500 -# define SLANG_VC 9 -# else -# error "unknown version of Visual C++ compiler" -# endif -# elif defined(__clang__) -# define SLANG_CLANG 1 -# elif defined(__SNC__) -# define SLANG_SNC 1 -# elif defined(__ghs__) -# define SLANG_GHS 1 -# elif defined(__GNUC__) /* note: __clang__, __SNC__, or __ghs__ imply __GNUC__ */ -# define SLANG_GCC 1 -# else -# error "unknown compiler" -# endif -/* -Any compilers not detected by the above logic are now now explicitly zeroed out. -*/ -# ifndef SLANG_VC -# define SLANG_VC 0 -# endif -# ifndef SLANG_CLANG -# define SLANG_CLANG 0 -# endif -# ifndef SLANG_SNC -# define SLANG_SNC 0 -# endif -# ifndef SLANG_GHS -# define SLANG_GHS 0 -# endif -# ifndef SLANG_GCC -# define SLANG_GCC 0 -# endif + /* + Compiler defines, see http://sourceforge.net/p/predef/wiki/Compilers/ + NOTE that SLANG_VC holds the compiler version - not just 1 or 0 + */ + #if defined(_MSC_VER) + #if _MSC_VER >= 1900 + #define SLANG_VC 14 + #elif _MSC_VER >= 1800 + #define SLANG_VC 12 + #elif _MSC_VER >= 1700 + #define SLANG_VC 11 + #elif _MSC_VER >= 1600 + #define SLANG_VC 10 + #elif _MSC_VER >= 1500 + #define SLANG_VC 9 + #else + #error "unknown version of Visual C++ compiler" + #endif + #elif defined(__clang__) + #define SLANG_CLANG 1 + #elif defined(__SNC__) + #define SLANG_SNC 1 + #elif defined(__ghs__) + #define SLANG_GHS 1 + #elif defined(__GNUC__) /* note: __clang__, __SNC__, or __ghs__ imply __GNUC__ */ + #define SLANG_GCC 1 + #else + #error "unknown compiler" + #endif + /* + Any compilers not detected by the above logic are now now explicitly zeroed out. + */ + #ifndef SLANG_VC + #define SLANG_VC 0 + #endif + #ifndef SLANG_CLANG + #define SLANG_CLANG 0 + #endif + #ifndef SLANG_SNC + #define SLANG_SNC 0 + #endif + #ifndef SLANG_GHS + #define SLANG_GHS 0 + #endif + #ifndef SLANG_GCC + #define SLANG_GCC 0 + #endif #endif /* SLANG_COMPILER */ /* @@ -78,86 +78,86 @@ used later in the file. Most applications should not need to touch this section. */ #ifndef SLANG_PLATFORM -# define SLANG_PLATFORM -/** -Operating system defines, see http://sourceforge.net/p/predef/wiki/OperatingSystems/ -*/ -# if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_PARTITION_APP -# define SLANG_WINRT 1 /* Windows Runtime, either on Windows RT or Windows 8 */ -# elif defined(XBOXONE) -# define SLANG_XBOXONE 1 -# elif defined(_WIN64) /* note: XBOXONE implies _WIN64 */ -# define SLANG_WIN64 1 -# elif defined(_M_PPC) -# define SLANG_X360 1 -# elif defined(_WIN32) /* note: _M_PPC implies _WIN32 */ -# define SLANG_WIN32 1 -# elif defined(__ANDROID__) -# define SLANG_ANDROID 1 -# elif defined(__linux__) || defined(__CYGWIN__) /* note: __ANDROID__ implies __linux__ */ -# define SLANG_LINUX 1 -# elif defined(__APPLE__) -# include "TargetConditionals.h" -# if TARGET_OS_MAC -# define SLANG_OSX 1 -# else -# define SLANG_IOS 1 -# endif -# elif defined(__CELLOS_LV2__) -# define SLANG_PS3 1 -# elif defined(__ORBIS__) -# define SLANG_PS4 1 -# elif defined(__SNC__) && defined(__arm__) -# define SLANG_PSP2 1 -# elif defined(__ghs__) -# define SLANG_WIIU 1 -# elif defined(__EMSCRIPTEN__) -# define SLANG_WASM 1 -# else -# error "unknown target platform" -# endif -/* -Any platforms not detected by the above logic are now now explicitly zeroed out. -*/ -# ifndef SLANG_WINRT -# define SLANG_WINRT 0 -# endif -# ifndef SLANG_XBOXONE -# define SLANG_XBOXONE 0 -# endif -# ifndef SLANG_WIN64 -# define SLANG_WIN64 0 -# endif -# ifndef SLANG_X360 -# define SLANG_X360 0 -# endif -# ifndef SLANG_WIN32 -# define SLANG_WIN32 0 -# endif -# ifndef SLANG_ANDROID -# define SLANG_ANDROID 0 -# endif -# ifndef SLANG_LINUX -# define SLANG_LINUX 0 -# endif -# ifndef SLANG_IOS -# define SLANG_IOS 0 -# endif -# ifndef SLANG_OSX -# define SLANG_OSX 0 -# endif -# ifndef SLANG_PS3 -# define SLANG_PS3 0 -# endif -# ifndef SLANG_PS4 -# define SLANG_PS4 0 -# endif -# ifndef SLANG_PSP2 -# define SLANG_PSP2 0 -# endif -# ifndef SLANG_WIIU -# define SLANG_WIIU 0 -# endif + #define SLANG_PLATFORM + /** + Operating system defines, see http://sourceforge.net/p/predef/wiki/OperatingSystems/ + */ + #if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_PARTITION_APP + #define SLANG_WINRT 1 /* Windows Runtime, either on Windows RT or Windows 8 */ + #elif defined(XBOXONE) + #define SLANG_XBOXONE 1 + #elif defined(_WIN64) /* note: XBOXONE implies _WIN64 */ + #define SLANG_WIN64 1 + #elif defined(_M_PPC) + #define SLANG_X360 1 + #elif defined(_WIN32) /* note: _M_PPC implies _WIN32 */ + #define SLANG_WIN32 1 + #elif defined(__ANDROID__) + #define SLANG_ANDROID 1 + #elif defined(__linux__) || defined(__CYGWIN__) /* note: __ANDROID__ implies __linux__ */ + #define SLANG_LINUX 1 + #elif defined(__APPLE__) + #include "TargetConditionals.h" + #if TARGET_OS_MAC + #define SLANG_OSX 1 + #else + #define SLANG_IOS 1 + #endif + #elif defined(__CELLOS_LV2__) + #define SLANG_PS3 1 + #elif defined(__ORBIS__) + #define SLANG_PS4 1 + #elif defined(__SNC__) && defined(__arm__) + #define SLANG_PSP2 1 + #elif defined(__ghs__) + #define SLANG_WIIU 1 + #elif defined(__EMSCRIPTEN__) + #define SLANG_WASM 1 + #else + #error "unknown target platform" + #endif + /* + Any platforms not detected by the above logic are now now explicitly zeroed out. + */ + #ifndef SLANG_WINRT + #define SLANG_WINRT 0 + #endif + #ifndef SLANG_XBOXONE + #define SLANG_XBOXONE 0 + #endif + #ifndef SLANG_WIN64 + #define SLANG_WIN64 0 + #endif + #ifndef SLANG_X360 + #define SLANG_X360 0 + #endif + #ifndef SLANG_WIN32 + #define SLANG_WIN32 0 + #endif + #ifndef SLANG_ANDROID + #define SLANG_ANDROID 0 + #endif + #ifndef SLANG_LINUX + #define SLANG_LINUX 0 + #endif + #ifndef SLANG_IOS + #define SLANG_IOS 0 + #endif + #ifndef SLANG_OSX + #define SLANG_OSX 0 + #endif + #ifndef SLANG_PS3 + #define SLANG_PS3 0 + #endif + #ifndef SLANG_PS4 + #define SLANG_PS4 0 + #endif + #ifndef SLANG_PSP2 + #define SLANG_PSP2 0 + #endif + #ifndef SLANG_WIIU + #define SLANG_WIIU 0 + #endif #endif /* SLANG_PLATFORM */ /* Shorthands for "families" of compilers/platforms */ @@ -165,57 +165,58 @@ Any platforms not detected by the above logic are now now explicitly zeroed out. #define SLANG_WINDOWS_FAMILY (SLANG_WINRT || SLANG_WIN32 || SLANG_WIN64) #define SLANG_MICROSOFT_FAMILY (SLANG_XBOXONE || SLANG_X360 || SLANG_WINDOWS_FAMILY) #define SLANG_LINUX_FAMILY (SLANG_LINUX || SLANG_ANDROID) -#define SLANG_APPLE_FAMILY (SLANG_IOS || SLANG_OSX) /* equivalent to #if __APPLE__ */ -#define SLANG_UNIX_FAMILY (SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY) /* shortcut for unix/posix platforms */ +#define SLANG_APPLE_FAMILY (SLANG_IOS || SLANG_OSX) /* equivalent to #if __APPLE__ */ +#define SLANG_UNIX_FAMILY \ + (SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY) /* shortcut for unix/posix platforms */ /* Macros concerning DirectX */ #if !defined(SLANG_CONFIG_DX_ON_VK) || !SLANG_CONFIG_DX_ON_VK -# define SLANG_ENABLE_DXVK 0 -# define SLANG_ENABLE_VKD3D 0 + #define SLANG_ENABLE_DXVK 0 + #define SLANG_ENABLE_VKD3D 0 #else -# define SLANG_ENABLE_DXVK 1 -# define SLANG_ENABLE_VKD3D 1 + #define SLANG_ENABLE_DXVK 1 + #define SLANG_ENABLE_VKD3D 1 #endif #if SLANG_WINDOWS_FAMILY -# define SLANG_ENABLE_DIRECTX 1 -# define SLANG_ENABLE_DXGI_DEBUG 1 -# define SLANG_ENABLE_DXBC_SUPPORT 1 -# define SLANG_ENABLE_PIX 1 + #define SLANG_ENABLE_DIRECTX 1 + #define SLANG_ENABLE_DXGI_DEBUG 1 + #define SLANG_ENABLE_DXBC_SUPPORT 1 + #define SLANG_ENABLE_PIX 1 #elif SLANG_LINUX_FAMILY -# define SLANG_ENABLE_DIRECTX (SLANG_ENABLE_DXVK || SLANG_ENABLE_VKD3D) -# define SLANG_ENABLE_DXGI_DEBUG 0 -# define SLANG_ENABLE_DXBC_SUPPORT 0 -# define SLANG_ENABLE_PIX 0 + #define SLANG_ENABLE_DIRECTX (SLANG_ENABLE_DXVK || SLANG_ENABLE_VKD3D) + #define SLANG_ENABLE_DXGI_DEBUG 0 + #define SLANG_ENABLE_DXBC_SUPPORT 0 + #define SLANG_ENABLE_PIX 0 #else -# define SLANG_ENABLE_DIRECTX 0 -# define SLANG_ENABLE_DXGI_DEBUG 0 -# define SLANG_ENABLE_DXBC_SUPPORT 0 -# define SLANG_ENABLE_PIX 0 + #define SLANG_ENABLE_DIRECTX 0 + #define SLANG_ENABLE_DXGI_DEBUG 0 + #define SLANG_ENABLE_DXBC_SUPPORT 0 + #define SLANG_ENABLE_PIX 0 #endif /* Macro for declaring if a method is no throw. Should be set before the return parameter. */ #ifndef SLANG_NO_THROW -# if SLANG_WINDOWS_FAMILY && !defined(SLANG_DISABLE_EXCEPTIONS) -# define SLANG_NO_THROW __declspec(nothrow) -# endif + #if SLANG_WINDOWS_FAMILY && !defined(SLANG_DISABLE_EXCEPTIONS) + #define SLANG_NO_THROW __declspec(nothrow) + #endif #endif #ifndef SLANG_NO_THROW -# define SLANG_NO_THROW + #define SLANG_NO_THROW #endif /* The `SLANG_STDCALL` and `SLANG_MCALL` defines are used to set the calling convention for interface methods. */ #ifndef SLANG_STDCALL -# if SLANG_MICROSOFT_FAMILY -# define SLANG_STDCALL __stdcall -# else -# define SLANG_STDCALL -# endif + #if SLANG_MICROSOFT_FAMILY + #define SLANG_STDCALL __stdcall + #else + #define SLANG_STDCALL + #endif #endif #ifndef SLANG_MCALL -# define SLANG_MCALL SLANG_STDCALL + #define SLANG_MCALL SLANG_STDCALL #endif @@ -224,94 +225,94 @@ convention for interface methods. #endif #if defined(_MSC_VER) -# define SLANG_DLL_EXPORT __declspec(dllexport) + #define SLANG_DLL_EXPORT __declspec(dllexport) #else -# if 0 && __GNUC__ >= 4 + #if 0 && __GNUC__ >= 4 // Didn't work on latest gcc on linux.. so disable for now // https://gcc.gnu.org/wiki/Visibility -# define SLANG_DLL_EXPORT __attribute__ ((dllexport)) -# else -# define SLANG_DLL_EXPORT __attribute__((__visibility__("default"))) -# endif + #define SLANG_DLL_EXPORT __attribute__((dllexport)) + #else + #define SLANG_DLL_EXPORT __attribute__((__visibility__("default"))) + #endif #endif #if defined(SLANG_DYNAMIC) -# if defined(_MSC_VER) -# ifdef SLANG_DYNAMIC_EXPORT -# define SLANG_API SLANG_DLL_EXPORT -# else -# define SLANG_API __declspec(dllimport) -# endif -# else + #if defined(_MSC_VER) + #ifdef SLANG_DYNAMIC_EXPORT + #define SLANG_API SLANG_DLL_EXPORT + #else + #define SLANG_API __declspec(dllimport) + #endif + #else // TODO: need to consider compiler capabilities -//# ifdef SLANG_DYNAMIC_EXPORT -# define SLANG_API SLANG_DLL_EXPORT -//# endif -# endif + // # ifdef SLANG_DYNAMIC_EXPORT + #define SLANG_API SLANG_DLL_EXPORT + // # endif + #endif #endif #ifndef SLANG_API -# define SLANG_API + #define SLANG_API #endif // GCC Specific #if SLANG_GCC_FAMILY -# define SLANG_NO_INLINE __attribute__((noinline)) -# define SLANG_FORCE_INLINE inline __attribute__((always_inline)) -# define SLANG_BREAKPOINT(id) __builtin_trap(); -# define SLANG_ALIGN_OF(T) __alignof__(T) + #define SLANG_NO_INLINE __attribute__((noinline)) + #define SLANG_FORCE_INLINE inline __attribute__((always_inline)) + #define SLANG_BREAKPOINT(id) __builtin_trap(); + #define SLANG_ALIGN_OF(T) __alignof__(T) #endif // SLANG_GCC_FAMILY #if SLANG_GCC_FAMILY || defined(__clang__) -// Use the builtin directly so we don't need to have an include of stddef.h -# define SLANG_OFFSET_OF(T, ELEMENT) __builtin_offsetof(T, ELEMENT) + // Use the builtin directly so we don't need to have an include of stddef.h + #define SLANG_OFFSET_OF(T, ELEMENT) __builtin_offsetof(T, ELEMENT) #endif #ifndef SLANG_OFFSET_OF -# define SLANG_OFFSET_OF(T, ELEMENT) (size_t(&((T*)1)->ELEMENT) - 1) + #define SLANG_OFFSET_OF(T, ELEMENT) (size_t(&((T*)1)->ELEMENT) - 1) #endif // Microsoft VC specific #if SLANG_MICROSOFT_FAMILY -# define SLANG_NO_INLINE __declspec(noinline) -# define SLANG_FORCE_INLINE __forceinline -# define SLANG_BREAKPOINT(id) __debugbreak(); -# define SLANG_ALIGN_OF(T) __alignof(T) + #define SLANG_NO_INLINE __declspec(noinline) + #define SLANG_FORCE_INLINE __forceinline + #define SLANG_BREAKPOINT(id) __debugbreak(); + #define SLANG_ALIGN_OF(T) __alignof(T) -# define SLANG_INT64(x) (x##i64) -# define SLANG_UINT64(x) (x##ui64) + #define SLANG_INT64(x) (x##i64) + #define SLANG_UINT64(x) (x##ui64) #endif // SLANG_MICROSOFT_FAMILY #ifndef SLANG_FORCE_INLINE -# define SLANG_FORCE_INLINE inline + #define SLANG_FORCE_INLINE inline #endif #ifndef SLANG_NO_INLINE -# define SLANG_NO_INLINE + #define SLANG_NO_INLINE #endif #ifndef SLANG_COMPILE_TIME_ASSERT -# define SLANG_COMPILE_TIME_ASSERT(x) static_assert(x) + #define SLANG_COMPILE_TIME_ASSERT(x) static_assert(x) #endif #ifndef SLANG_BREAKPOINT -// Make it crash with a write to 0! -# define SLANG_BREAKPOINT(id) (*((int*)0) = int(id)); + // Make it crash with a write to 0! + #define SLANG_BREAKPOINT(id) (*((int*)0) = int(id)); #endif // Use for getting the amount of members of a standard C array. // Use 0[x] here to catch the case where x has an overloaded subscript operator -#define SLANG_COUNT_OF(x) (SlangSSizeT(sizeof(x)/sizeof(0[x]))) +#define SLANG_COUNT_OF(x) (SlangSSizeT(sizeof(x) / sizeof(0 [x]))) /// SLANG_INLINE exists to have a way to inline consistent with SLANG_ALWAYS_INLINE #define SLANG_INLINE inline // If explicilty disabled and not set, set to not available #if !defined(SLANG_HAS_EXCEPTIONS) && defined(SLANG_DISABLE_EXCEPTIONS) -# define SLANG_HAS_EXCEPTIONS 0 + #define SLANG_HAS_EXCEPTIONS 0 #endif // If not set, the default is exceptions are available #ifndef SLANG_HAS_EXCEPTIONS -# define SLANG_HAS_EXCEPTIONS 1 + #define SLANG_HAS_EXCEPTIONS 1 #endif // Other defines @@ -322,129 +323,130 @@ convention for interface methods. #define SLANG_CONCAT(X, Y) SLANG_CONCAT_HELPER(X, Y) #ifndef SLANG_UNUSED -# define SLANG_UNUSED(v) (void)v; + #define SLANG_UNUSED(v) (void)v; #endif #if defined(__llvm__) -# define SLANG_MAYBE_UNUSED [[maybe_unused]] + #define SLANG_MAYBE_UNUSED [[maybe_unused]] #else -# define SLANG_MAYBE_UNUSED + #define SLANG_MAYBE_UNUSED #endif // Used for doing constant literals #ifndef SLANG_INT64 -# define SLANG_INT64(x) (x##ll) + #define SLANG_INT64(x) (x##ll) #endif #ifndef SLANG_UINT64 -# define SLANG_UINT64(x) (x##ull) + #define SLANG_UINT64(x) (x##ull) #endif #ifdef __cplusplus -# define SLANG_EXTERN_C extern "C" + #define SLANG_EXTERN_C extern "C" #else -# define SLANG_EXTERN_C + #define SLANG_EXTERN_C #endif #ifdef __cplusplus -// C++ specific macros -// Clang -#if SLANG_CLANG -# if (__clang_major__*10 + __clang_minor__) >= 33 -# define SLANG_HAS_MOVE_SEMANTICS 1 -# define SLANG_HAS_ENUM_CLASS 1 -# define SLANG_OVERRIDE override -# endif - -// Gcc -#elif SLANG_GCC_FAMILY -// Check for C++11 -# if (__cplusplus >= 201103L) -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 -# define SLANG_HAS_MOVE_SEMANTICS 1 -# endif -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 -# define SLANG_HAS_ENUM_CLASS 1 -# endif -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 -# define SLANG_OVERRIDE override -# endif -# endif -# endif // SLANG_GCC_FAMILY - -// Visual Studio - -# if SLANG_VC -// C4481: nonstandard extension used: override specifier 'override' -# if _MSC_VER < 1700 -# pragma warning(disable : 4481) -# endif -# define SLANG_OVERRIDE override -# if _MSC_VER >= 1600 -# define SLANG_HAS_MOVE_SEMANTICS 1 -# endif -# if _MSC_VER >= 1700 -# define SLANG_HAS_ENUM_CLASS 1 -# endif -# endif // SLANG_VC - -// Set non set -# ifndef SLANG_OVERRIDE -# define SLANG_OVERRIDE -# endif -# ifndef SLANG_HAS_ENUM_CLASS -# define SLANG_HAS_ENUM_CLASS 0 -# endif -# ifndef SLANG_HAS_MOVE_SEMANTICS -# define SLANG_HAS_MOVE_SEMANTICS 0 -# endif + // C++ specific macros + // Clang + #if SLANG_CLANG + #if (__clang_major__ * 10 + __clang_minor__) >= 33 + #define SLANG_HAS_MOVE_SEMANTICS 1 + #define SLANG_HAS_ENUM_CLASS 1 + #define SLANG_OVERRIDE override + #endif + + // Gcc + #elif SLANG_GCC_FAMILY + // Check for C++11 + #if (__cplusplus >= 201103L) + #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 + #define SLANG_HAS_MOVE_SEMANTICS 1 + #endif + #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 + #define SLANG_HAS_ENUM_CLASS 1 + #endif + #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 + #define SLANG_OVERRIDE override + #endif + #endif + #endif // SLANG_GCC_FAMILY + + // Visual Studio + + #if SLANG_VC + // C4481: nonstandard extension used: override specifier 'override' + #if _MSC_VER < 1700 + #pragma warning(disable : 4481) + #endif + #define SLANG_OVERRIDE override + #if _MSC_VER >= 1600 + #define SLANG_HAS_MOVE_SEMANTICS 1 + #endif + #if _MSC_VER >= 1700 + #define SLANG_HAS_ENUM_CLASS 1 + #endif + #endif // SLANG_VC + + // Set non set + #ifndef SLANG_OVERRIDE + #define SLANG_OVERRIDE + #endif + #ifndef SLANG_HAS_ENUM_CLASS + #define SLANG_HAS_ENUM_CLASS 0 + #endif + #ifndef SLANG_HAS_MOVE_SEMANTICS + #define SLANG_HAS_MOVE_SEMANTICS 0 + #endif #endif // __cplusplus /* Macros for detecting processor */ #if defined(_M_ARM) || defined(__ARM_EABI__) -// This is special case for nVidia tegra -# define SLANG_PROCESSOR_ARM 1 + // This is special case for nVidia tegra + #define SLANG_PROCESSOR_ARM 1 #elif defined(__i386__) || defined(_M_IX86) -# define SLANG_PROCESSOR_X86 1 + #define SLANG_PROCESSOR_X86 1 #elif defined(_M_AMD64) || defined(_M_X64) || defined(__amd64) || defined(__x86_64) -# define SLANG_PROCESSOR_X86_64 1 + #define SLANG_PROCESSOR_X86_64 1 #elif defined(_PPC_) || defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) -# if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || defined(__64BIT__) || defined(_LP64) || defined(__LP64__) -# define SLANG_PROCESSOR_POWER_PC_64 1 -# else -# define SLANG_PROCESSOR_POWER_PC 1 -# endif + #if defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) || \ + defined(__64BIT__) || defined(_LP64) || defined(__LP64__) + #define SLANG_PROCESSOR_POWER_PC_64 1 + #else + #define SLANG_PROCESSOR_POWER_PC 1 + #endif #elif defined(__arm__) -# define SLANG_PROCESSOR_ARM 1 + #define SLANG_PROCESSOR_ARM 1 #elif defined(_M_ARM64) || defined(__aarch64__) -# define SLANG_PROCESSOR_ARM_64 1 + #define SLANG_PROCESSOR_ARM_64 1 #elif defined(__EMSCRIPTEN__) -# define SLANG_PROCESSOR_WASM 1 + #define SLANG_PROCESSOR_WASM 1 #endif #ifndef SLANG_PROCESSOR_ARM -# define SLANG_PROCESSOR_ARM 0 + #define SLANG_PROCESSOR_ARM 0 #endif #ifndef SLANG_PROCESSOR_ARM_64 -# define SLANG_PROCESSOR_ARM_64 0 + #define SLANG_PROCESSOR_ARM_64 0 #endif #ifndef SLANG_PROCESSOR_X86 -# define SLANG_PROCESSOR_X86 0 + #define SLANG_PROCESSOR_X86 0 #endif #ifndef SLANG_PROCESSOR_X86_64 -# define SLANG_PROCESSOR_X86_64 0 + #define SLANG_PROCESSOR_X86_64 0 #endif #ifndef SLANG_PROCESSOR_POWER_PC -# define SLANG_PROCESSOR_POWER_PC 0 + #define SLANG_PROCESSOR_POWER_PC 0 #endif #ifndef SLANG_PROCESSOR_POWER_PC_64 -# define SLANG_PROCESSOR_POWER_PC_64 0 + #define SLANG_PROCESSOR_POWER_PC_64 0 #endif // Processor families @@ -454,48 +456,49 @@ convention for interface methods. #define SLANG_PROCESSOR_FAMILY_POWER_PC (SLANG_PROCESSOR_POWER_PC_64 | SLANG_PROCESSOR_POWER_PC) // Pointer size -#define SLANG_PTR_IS_64 (SLANG_PROCESSOR_ARM_64 | SLANG_PROCESSOR_X86_64 | SLANG_PROCESSOR_POWER_PC_64) +#define SLANG_PTR_IS_64 \ + (SLANG_PROCESSOR_ARM_64 | SLANG_PROCESSOR_X86_64 | SLANG_PROCESSOR_POWER_PC_64) #define SLANG_PTR_IS_32 (SLANG_PTR_IS_64 ^ 1) // Processor features #if SLANG_PROCESSOR_FAMILY_X86 -# define SLANG_LITTLE_ENDIAN 1 -# define SLANG_UNALIGNED_ACCESS 1 + #define SLANG_LITTLE_ENDIAN 1 + #define SLANG_UNALIGNED_ACCESS 1 #elif SLANG_PROCESSOR_FAMILY_ARM -# if defined(__ARMEB__) -# define SLANG_BIG_ENDIAN 1 -# else -# define SLANG_LITTLE_ENDIAN 1 -# endif + #if defined(__ARMEB__) + #define SLANG_BIG_ENDIAN 1 + #else + #define SLANG_LITTLE_ENDIAN 1 + #endif #elif SLANG_PROCESSOR_FAMILY_POWER_PC -# define SLANG_BIG_ENDIAN 1 + #define SLANG_BIG_ENDIAN 1 #elif SLANG_WASM -# define SLANG_LITTLE_ENDIAN 1 + #define SLANG_LITTLE_ENDIAN 1 #endif #ifndef SLANG_LITTLE_ENDIAN -# define SLANG_LITTLE_ENDIAN 0 + #define SLANG_LITTLE_ENDIAN 0 #endif #ifndef SLANG_BIG_ENDIAN -# define SLANG_BIG_ENDIAN 0 + #define SLANG_BIG_ENDIAN 0 #endif #ifndef SLANG_UNALIGNED_ACCESS -# define SLANG_UNALIGNED_ACCESS 0 + #define SLANG_UNALIGNED_ACCESS 0 #endif // One endianess must be set #if ((SLANG_BIG_ENDIAN | SLANG_LITTLE_ENDIAN) == 0) -# error "Couldn't determine endianess" + #error "Couldn't determine endianess" #endif -#ifndef SLANG_NO_INTTYPES -#include +#ifndef SLANG_NO_INTTYPES + #include #endif // ! SLANG_NO_INTTYPES -#ifndef SLANG_NO_STDDEF -#include +#ifndef SLANG_NO_STDDEF + #include #endif // ! SLANG_NO_STDDEF #ifdef __cplusplus @@ -510,32 +513,33 @@ extern "C" @file slang.h */ - typedef uint32_t SlangUInt32; - typedef int32_t SlangInt32; + typedef uint32_t SlangUInt32; + typedef int32_t SlangInt32; // Use SLANG_PTR_ macros to determine SlangInt/SlangUInt types. - // This is used over say using size_t/ptrdiff_t/intptr_t/uintptr_t, because on some targets, these types are distinct from - // their uint_t/int_t equivalents and so produce ambiguity with function overloading. + // This is used over say using size_t/ptrdiff_t/intptr_t/uintptr_t, because on some targets, + // these types are distinct from their uint_t/int_t equivalents and so produce ambiguity with + // function overloading. // - // SlangSizeT is helpful as on some compilers size_t is distinct from a regular integer type and so overloading doesn't work. - // Casting to SlangSizeT works around this. + // SlangSizeT is helpful as on some compilers size_t is distinct from a regular integer type and + // so overloading doesn't work. Casting to SlangSizeT works around this. #if SLANG_PTR_IS_64 - typedef int64_t SlangInt; - typedef uint64_t SlangUInt; + typedef int64_t SlangInt; + typedef uint64_t SlangUInt; - typedef int64_t SlangSSizeT; - typedef uint64_t SlangSizeT; + typedef int64_t SlangSSizeT; + typedef uint64_t SlangSizeT; #else - typedef int32_t SlangInt; - typedef uint32_t SlangUInt; +typedef int32_t SlangInt; +typedef uint32_t SlangUInt; - typedef int32_t SlangSSizeT; - typedef uint32_t SlangSizeT; +typedef int32_t SlangSSizeT; +typedef uint32_t SlangSizeT; #endif typedef bool SlangBool; - + /*! @brief Severity of a diagnostic generated by the compiler. Values come from the enum below, with higher values representing more severe @@ -549,8 +553,9 @@ extern "C" SLANG_SEVERITY_NOTE, /**< An informative message. */ SLANG_SEVERITY_WARNING, /**< A warning, which indicates a possible proble. */ SLANG_SEVERITY_ERROR, /**< An error, indicating that compilation failed. */ - SLANG_SEVERITY_FATAL, /**< An unrecoverable error, which forced compilation to abort. */ - SLANG_SEVERITY_INTERNAL, /**< An internal error, indicating a logic error in the compiler. */ + SLANG_SEVERITY_FATAL, /**< An unrecoverable error, which forced compilation to abort. */ + SLANG_SEVERITY_INTERNAL, /**< An internal error, indicating a logic error in the compiler. + */ }; typedef int SlangDiagnosticFlags; @@ -572,11 +577,11 @@ extern "C" /* NOTE! To keep binary compatibility care is needed with this enum! - * To add value, only add at the bottom (before COUNT_OF) + * To add value, only add at the bottom (before COUNT_OF) * To remove a value, add _DEPRECATED as a suffix, but leave in the list - - This will make the enum values stable, and compatible with libraries that might not use the latest - enum values. + + This will make the enum values stable, and compatible with libraries that might not use the + latest enum values. */ typedef int SlangCompileTargetIntegral; enum SlangCompileTarget : SlangCompileTargetIntegral @@ -584,8 +589,8 @@ extern "C" SLANG_TARGET_UNKNOWN, SLANG_TARGET_NONE, SLANG_GLSL, - SLANG_GLSL_VULKAN_DEPRECATED, //< deprecated and removed: just use `SLANG_GLSL`. - SLANG_GLSL_VULKAN_ONE_DESC_DEPRECATED, //< deprecated and removed. + SLANG_GLSL_VULKAN_DEPRECATED, //< deprecated and removed: just use `SLANG_GLSL`. + SLANG_GLSL_VULKAN_ONE_DESC_DEPRECATED, //< deprecated and removed. SLANG_HLSL, SLANG_SPIRV, SLANG_SPIRV_ASM, @@ -593,25 +598,27 @@ extern "C" SLANG_DXBC_ASM, SLANG_DXIL, SLANG_DXIL_ASM, - SLANG_C_SOURCE, ///< The C language - SLANG_CPP_SOURCE, ///< C++ code for shader kernels. - SLANG_HOST_EXECUTABLE, ///< Standalone binary executable (for hosting CPU/OS) - SLANG_SHADER_SHARED_LIBRARY, ///< A shared library/Dll for shader kernels (for hosting CPU/OS) - SLANG_SHADER_HOST_CALLABLE, ///< A CPU target that makes the compiled shader code available to be run immediately - SLANG_CUDA_SOURCE, ///< Cuda source - SLANG_PTX, ///< PTX - SLANG_CUDA_OBJECT_CODE, ///< Object code that contains CUDA functions. - SLANG_OBJECT_CODE, ///< Object code that can be used for later linking - SLANG_HOST_CPP_SOURCE, ///< C++ code for host library or executable. - SLANG_HOST_HOST_CALLABLE, ///< Host callable host code (ie non kernel/shader) - SLANG_CPP_PYTORCH_BINDING, ///< C++ PyTorch binding code. - SLANG_METAL, ///< Metal shading language - SLANG_METAL_LIB, ///< Metal library - SLANG_METAL_LIB_ASM, ///< Metal library assembly - SLANG_HOST_SHARED_LIBRARY, ///< A shared library/Dll for host code (for hosting CPU/OS) - SLANG_WGSL, ///< WebGPU shading language - SLANG_WGSL_SPIRV_ASM, ///< SPIR-V assembly via WebGPU shading language - SLANG_WGSL_SPIRV, ///< SPIR-V via WebGPU shading language + SLANG_C_SOURCE, ///< The C language + SLANG_CPP_SOURCE, ///< C++ code for shader kernels. + SLANG_HOST_EXECUTABLE, ///< Standalone binary executable (for hosting CPU/OS) + SLANG_SHADER_SHARED_LIBRARY, ///< A shared library/Dll for shader kernels (for hosting + ///< CPU/OS) + SLANG_SHADER_HOST_CALLABLE, ///< A CPU target that makes the compiled shader code available + ///< to be run immediately + SLANG_CUDA_SOURCE, ///< Cuda source + SLANG_PTX, ///< PTX + SLANG_CUDA_OBJECT_CODE, ///< Object code that contains CUDA functions. + SLANG_OBJECT_CODE, ///< Object code that can be used for later linking + SLANG_HOST_CPP_SOURCE, ///< C++ code for host library or executable. + SLANG_HOST_HOST_CALLABLE, ///< Host callable host code (ie non kernel/shader) + SLANG_CPP_PYTORCH_BINDING, ///< C++ PyTorch binding code. + SLANG_METAL, ///< Metal shading language + SLANG_METAL_LIB, ///< Metal library + SLANG_METAL_LIB_ASM, ///< Metal library assembly + SLANG_HOST_SHARED_LIBRARY, ///< A shared library/Dll for host code (for hosting CPU/OS) + SLANG_WGSL, ///< WebGPU shading language + SLANG_WGSL_SPIRV_ASM, ///< SPIR-V assembly via WebGPU shading language + SLANG_WGSL_SPIRV, ///< SPIR-V via WebGPU shading language SLANG_TARGET_COUNT_OF, }; @@ -637,15 +644,16 @@ extern "C" SLANG_PASS_THROUGH_DXC, SLANG_PASS_THROUGH_GLSLANG, SLANG_PASS_THROUGH_SPIRV_DIS, - SLANG_PASS_THROUGH_CLANG, ///< Clang C/C++ compiler - SLANG_PASS_THROUGH_VISUAL_STUDIO, ///< Visual studio C/C++ compiler - SLANG_PASS_THROUGH_GCC, ///< GCC C/C++ compiler - SLANG_PASS_THROUGH_GENERIC_C_CPP, ///< Generic C or C++ compiler, which is decided by the source type - SLANG_PASS_THROUGH_NVRTC, ///< NVRTC Cuda compiler - SLANG_PASS_THROUGH_LLVM, ///< LLVM 'compiler' - includes LLVM and Clang - SLANG_PASS_THROUGH_SPIRV_OPT, ///< SPIRV-opt - SLANG_PASS_THROUGH_METAL, ///< Metal compiler - SLANG_PASS_THROUGH_TINT, ///< Tint WGSL compiler + SLANG_PASS_THROUGH_CLANG, ///< Clang C/C++ compiler + SLANG_PASS_THROUGH_VISUAL_STUDIO, ///< Visual studio C/C++ compiler + SLANG_PASS_THROUGH_GCC, ///< GCC C/C++ compiler + SLANG_PASS_THROUGH_GENERIC_C_CPP, ///< Generic C or C++ compiler, which is decided by the + ///< source type + SLANG_PASS_THROUGH_NVRTC, ///< NVRTC Cuda compiler + SLANG_PASS_THROUGH_LLVM, ///< LLVM 'compiler' - includes LLVM and Clang + SLANG_PASS_THROUGH_SPIRV_OPT, ///< SPIRV-opt + SLANG_PASS_THROUGH_METAL, ///< Metal compiler + SLANG_PASS_THROUGH_TINT, ///< Tint WGSL compiler SLANG_PASS_THROUGH_COUNT_OF, }; @@ -655,7 +663,7 @@ extern "C" { SLANG_ARCHIVE_TYPE_UNDEFINED, SLANG_ARCHIVE_TYPE_ZIP, - SLANG_ARCHIVE_TYPE_RIFF, ///< Riff container with no compression + SLANG_ARCHIVE_TYPE_RIFF, ///< Riff container with no compression SLANG_ARCHIVE_TYPE_RIFF_DEFLATE, SLANG_ARCHIVE_TYPE_RIFF_LZ4, SLANG_ARCHIVE_TYPE_COUNT_OF, @@ -668,10 +676,10 @@ extern "C" enum { /* Do as little mangling of names as possible, to try to preserve original names */ - SLANG_COMPILE_FLAG_NO_MANGLING = 1 << 3, + SLANG_COMPILE_FLAG_NO_MANGLING = 1 << 3, /* Skip code generation step, just check the code and generate layout */ - SLANG_COMPILE_FLAG_NO_CODEGEN = 1 << 4, + SLANG_COMPILE_FLAG_NO_CODEGEN = 1 << 4, /* Obfuscate shader names on release products */ SLANG_COMPILE_FLAG_OBFUSCATE = 1 << 5, @@ -679,14 +687,14 @@ extern "C" /* Deprecated flags: kept around to allow existing applications to compile. Note that the relevant features will still be left in their default state. */ - SLANG_COMPILE_FLAG_NO_CHECKING = 0, - SLANG_COMPILE_FLAG_SPLIT_MIXED_TYPES = 0, + SLANG_COMPILE_FLAG_NO_CHECKING = 0, + SLANG_COMPILE_FLAG_SPLIT_MIXED_TYPES = 0, }; /*! @brief Flags to control code generation behavior of a compilation target */ typedef unsigned int SlangTargetFlags; - enum + enum { /* When compiling for a D3D Shader Model 5.1 or higher target, allocate distinct register spaces for parameter blocks. @@ -707,7 +715,8 @@ extern "C" /* When set, will generate SPIRV directly rather than via glslang. */ SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY = 1 << 10, }; - constexpr static SlangTargetFlags kDefaultTargetFlags = SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY; + constexpr static SlangTargetFlags kDefaultTargetFlags = + SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY; /*! @brief Options to control floating-point precision guarantees for a target. @@ -726,11 +735,14 @@ extern "C" typedef unsigned int SlangLineDirectiveModeIntegral; enum SlangLineDirectiveMode : SlangLineDirectiveModeIntegral { - SLANG_LINE_DIRECTIVE_MODE_DEFAULT = 0, /**< Default behavior: pick behavior base on target. */ - SLANG_LINE_DIRECTIVE_MODE_NONE, /**< Don't emit line directives at all. */ - SLANG_LINE_DIRECTIVE_MODE_STANDARD, /**< Emit standard C-style `#line` directives. */ - SLANG_LINE_DIRECTIVE_MODE_GLSL, /**< Emit GLSL-style directives with file *number* instead of name */ - SLANG_LINE_DIRECTIVE_MODE_SOURCE_MAP, /**< Use a source map to track line mappings (ie no #line will appear in emitting source) */ + SLANG_LINE_DIRECTIVE_MODE_DEFAULT = + 0, /**< Default behavior: pick behavior base on target. */ + SLANG_LINE_DIRECTIVE_MODE_NONE, /**< Don't emit line directives at all. */ + SLANG_LINE_DIRECTIVE_MODE_STANDARD, /**< Emit standard C-style `#line` directives. */ + SLANG_LINE_DIRECTIVE_MODE_GLSL, /**< Emit GLSL-style directives with file *number* instead + of name */ + SLANG_LINE_DIRECTIVE_MODE_SOURCE_MAP, /**< Use a source map to track line mappings (ie no + #line will appear in emitting source) */ }; typedef int SlangSourceLanguageIntegral; @@ -796,24 +808,28 @@ extern "C" typedef SlangUInt32 SlangDebugInfoLevelIntegral; enum SlangDebugInfoLevel : SlangDebugInfoLevelIntegral { - SLANG_DEBUG_INFO_LEVEL_NONE = 0, /**< Don't emit debug information at all. */ - SLANG_DEBUG_INFO_LEVEL_MINIMAL, /**< Emit as little debug information as possible, while still supporting stack trackes. */ - SLANG_DEBUG_INFO_LEVEL_STANDARD, /**< Emit whatever is the standard level of debug information for each target. */ - SLANG_DEBUG_INFO_LEVEL_MAXIMAL, /**< Emit as much debug infromation as possible for each target. */ - + SLANG_DEBUG_INFO_LEVEL_NONE = 0, /**< Don't emit debug information at all. */ + SLANG_DEBUG_INFO_LEVEL_MINIMAL, /**< Emit as little debug information as possible, while + still supporting stack trackes. */ + SLANG_DEBUG_INFO_LEVEL_STANDARD, /**< Emit whatever is the standard level of debug + information for each target. */ + SLANG_DEBUG_INFO_LEVEL_MAXIMAL, /**< Emit as much debug infromation as possible for each + target. */ }; /* Describes the debugging information format produced during a compilation. */ typedef SlangUInt32 SlangDebugInfoFormatIntegral; enum SlangDebugInfoFormat : SlangDebugInfoFormatIntegral { - SLANG_DEBUG_INFO_FORMAT_DEFAULT, ///< Use the default debugging format for the target - SLANG_DEBUG_INFO_FORMAT_C7, ///< CodeView C7 format (typically means debugging infomation is embedded in the binary) - SLANG_DEBUG_INFO_FORMAT_PDB, ///< Program database - - SLANG_DEBUG_INFO_FORMAT_STABS, ///< Stabs - SLANG_DEBUG_INFO_FORMAT_COFF, ///< COFF debug info - SLANG_DEBUG_INFO_FORMAT_DWARF, ///< DWARF debug info (we may want to support specifying the version) + SLANG_DEBUG_INFO_FORMAT_DEFAULT, ///< Use the default debugging format for the target + SLANG_DEBUG_INFO_FORMAT_C7, ///< CodeView C7 format (typically means debugging infomation is + ///< embedded in the binary) + SLANG_DEBUG_INFO_FORMAT_PDB, ///< Program database + + SLANG_DEBUG_INFO_FORMAT_STABS, ///< Stabs + SLANG_DEBUG_INFO_FORMAT_COFF, ///< COFF debug info + SLANG_DEBUG_INFO_FORMAT_DWARF, ///< DWARF debug info (we may want to support specifying the + ///< version) SLANG_DEBUG_INFO_FORMAT_COUNT_OF, }; @@ -821,192 +837,197 @@ extern "C" typedef SlangUInt32 SlangOptimizationLevelIntegral; enum SlangOptimizationLevel : SlangOptimizationLevelIntegral { - SLANG_OPTIMIZATION_LEVEL_NONE = 0, /**< Don't optimize at all. */ - SLANG_OPTIMIZATION_LEVEL_DEFAULT, /**< Default optimization level: balance code quality and compilation time. */ - SLANG_OPTIMIZATION_LEVEL_HIGH, /**< Optimize aggressively. */ - SLANG_OPTIMIZATION_LEVEL_MAXIMAL, /**< Include optimizations that may take a very long time, or may involve severe space-vs-speed tradeoffs */ + SLANG_OPTIMIZATION_LEVEL_NONE = 0, /**< Don't optimize at all. */ + SLANG_OPTIMIZATION_LEVEL_DEFAULT, /**< Default optimization level: balance code quality and + compilation time. */ + SLANG_OPTIMIZATION_LEVEL_HIGH, /**< Optimize aggressively. */ + SLANG_OPTIMIZATION_LEVEL_MAXIMAL, /**< Include optimizations that may take a very long time, + or may involve severe space-vs-speed tradeoffs */ }; // All compiler option names supported by Slang. namespace slang { - enum class CompilerOptionName - { - MacroDefine, // stringValue0: macro name; stringValue1: macro value - DepFile, - EntryPointName, - Specialize, - Help, - HelpStyle, - Include, // stringValue: additional include path. - Language, - MatrixLayoutColumn, // bool - MatrixLayoutRow, // bool - ZeroInitialize, // bool - IgnoreCapabilities, // bool - RestrictiveCapabilityCheck, // bool - ModuleName, // stringValue0: module name. - Output, - Profile, // intValue0: profile - Stage, // intValue0: stage - Target, // intValue0: CodeGenTarget - Version, - WarningsAsErrors, // stringValue0: "all" or comma separated list of warning codes or names. - DisableWarnings, // stringValue0: comma separated list of warning codes or names. - EnableWarning, // stringValue0: warning code or name. - DisableWarning, // stringValue0: warning code or name. - DumpWarningDiagnostics, - InputFilesRemain, - EmitIr, // bool - ReportDownstreamTime, // bool - ReportPerfBenchmark, // bool - ReportCheckpointIntermediates, // bool - SkipSPIRVValidation, // bool - SourceEmbedStyle, - SourceEmbedName, - SourceEmbedLanguage, - DisableShortCircuit, // bool - MinimumSlangOptimization, // bool - DisableNonEssentialValidations, // bool - DisableSourceMap, // bool - UnscopedEnum, // bool - PreserveParameters, // bool: preserve all resource parameters in the output code. - - // Target - - Capability, // intValue0: CapabilityName - DefaultImageFormatUnknown, // bool - DisableDynamicDispatch, // bool - DisableSpecialization, // bool - FloatingPointMode, // intValue0: FloatingPointMode - DebugInformation, // intValue0: DebugInfoLevel - LineDirectiveMode, - Optimization, // intValue0: OptimizationLevel - Obfuscate, // bool - - VulkanBindShift, // intValue0 (higher 8 bits): kind; intValue0(lower bits): set; intValue1: shift - VulkanBindGlobals, // intValue0: index; intValue1: set - VulkanInvertY, // bool - VulkanUseDxPositionW, // bool - VulkanUseEntryPointName, // bool - VulkanUseGLLayout, // bool - VulkanEmitReflection, // bool - - GLSLForceScalarLayout, // bool - EnableEffectAnnotations, // bool - - EmitSpirvViaGLSL, // bool - EmitSpirvDirectly, // bool - SPIRVCoreGrammarJSON, // stringValue0: json path - IncompleteLibrary, // bool, when set, will not issue an error when the linked program has unresolved extern function symbols. - - // Downstream - - CompilerPath, - DefaultDownstreamCompiler, - DownstreamArgs, // stringValue0: downstream compiler name. stringValue1: argument list, one per line. - PassThrough, - - // Repro - - DumpRepro, - DumpReproOnError, - ExtractRepro, - LoadRepro, - LoadReproDirectory, - ReproFallbackDirectory, - - // Debugging - - DumpAst, - DumpIntermediatePrefix, - DumpIntermediates, // bool - DumpIr, // bool - DumpIrIds, - PreprocessorOutput, - OutputIncludes, - ReproFileSystem, - SerialIr, // bool - SkipCodeGen, // bool - ValidateIr, // bool - VerbosePaths, - VerifyDebugSerialIr, - NoCodeGen, // Not used. - - // Experimental - - FileSystem, - Heterogeneous, - NoMangle, - NoHLSLBinding, - NoHLSLPackConstantBufferElements, - ValidateUniformity, - AllowGLSL, - EnableExperimentalPasses, - - // Internal - - ArchiveType, - CompileCoreModule, - Doc, - IrCompression, - LoadCoreModule, - ReferenceModule, - SaveCoreModule, - SaveCoreModuleBinSource, - TrackLiveness, - LoopInversion, // bool, enable loop inversion optimization - - // Deprecated - ParameterBlocksUseRegisterSpaces, - - CountOfParsableOptions, - - // Used in parsed options only. - DebugInformationFormat, // intValue0: DebugInfoFormat - VulkanBindShiftAll, // intValue0: kind; intValue1: shift - GenerateWholeProgram, // bool - UseUpToDateBinaryModule, // bool, when set, will only load - // precompiled modules if it is up-to-date with its source. - EmbedDownstreamIR, // bool - ForceDXLayout, // bool - CountOf, - }; + enum class CompilerOptionName + { + MacroDefine, // stringValue0: macro name; stringValue1: macro value + DepFile, + EntryPointName, + Specialize, + Help, + HelpStyle, + Include, // stringValue: additional include path. + Language, + MatrixLayoutColumn, // bool + MatrixLayoutRow, // bool + ZeroInitialize, // bool + IgnoreCapabilities, // bool + RestrictiveCapabilityCheck, // bool + ModuleName, // stringValue0: module name. + Output, + Profile, // intValue0: profile + Stage, // intValue0: stage + Target, // intValue0: CodeGenTarget + Version, + WarningsAsErrors, // stringValue0: "all" or comma separated list of warning codes or names. + DisableWarnings, // stringValue0: comma separated list of warning codes or names. + EnableWarning, // stringValue0: warning code or name. + DisableWarning, // stringValue0: warning code or name. + DumpWarningDiagnostics, + InputFilesRemain, + EmitIr, // bool + ReportDownstreamTime, // bool + ReportPerfBenchmark, // bool + ReportCheckpointIntermediates, // bool + SkipSPIRVValidation, // bool + SourceEmbedStyle, + SourceEmbedName, + SourceEmbedLanguage, + DisableShortCircuit, // bool + MinimumSlangOptimization, // bool + DisableNonEssentialValidations, // bool + DisableSourceMap, // bool + UnscopedEnum, // bool + PreserveParameters, // bool: preserve all resource parameters in the output code. + + // Target + + Capability, // intValue0: CapabilityName + DefaultImageFormatUnknown, // bool + DisableDynamicDispatch, // bool + DisableSpecialization, // bool + FloatingPointMode, // intValue0: FloatingPointMode + DebugInformation, // intValue0: DebugInfoLevel + LineDirectiveMode, + Optimization, // intValue0: OptimizationLevel + Obfuscate, // bool + + VulkanBindShift, // intValue0 (higher 8 bits): kind; intValue0(lower bits): set; intValue1: + // shift + VulkanBindGlobals, // intValue0: index; intValue1: set + VulkanInvertY, // bool + VulkanUseDxPositionW, // bool + VulkanUseEntryPointName, // bool + VulkanUseGLLayout, // bool + VulkanEmitReflection, // bool + + GLSLForceScalarLayout, // bool + EnableEffectAnnotations, // bool + + EmitSpirvViaGLSL, // bool + EmitSpirvDirectly, // bool + SPIRVCoreGrammarJSON, // stringValue0: json path + IncompleteLibrary, // bool, when set, will not issue an error when the linked program has + // unresolved extern function symbols. + + // Downstream + + CompilerPath, + DefaultDownstreamCompiler, + DownstreamArgs, // stringValue0: downstream compiler name. stringValue1: argument list, one + // per line. + PassThrough, + + // Repro + + DumpRepro, + DumpReproOnError, + ExtractRepro, + LoadRepro, + LoadReproDirectory, + ReproFallbackDirectory, + + // Debugging + + DumpAst, + DumpIntermediatePrefix, + DumpIntermediates, // bool + DumpIr, // bool + DumpIrIds, + PreprocessorOutput, + OutputIncludes, + ReproFileSystem, + SerialIr, // bool + SkipCodeGen, // bool + ValidateIr, // bool + VerbosePaths, + VerifyDebugSerialIr, + NoCodeGen, // Not used. + + // Experimental + + FileSystem, + Heterogeneous, + NoMangle, + NoHLSLBinding, + NoHLSLPackConstantBufferElements, + ValidateUniformity, + AllowGLSL, + EnableExperimentalPasses, + + // Internal + + ArchiveType, + CompileCoreModule, + Doc, + IrCompression, + LoadCoreModule, + ReferenceModule, + SaveCoreModule, + SaveCoreModuleBinSource, + TrackLiveness, + LoopInversion, // bool, enable loop inversion optimization + + // Deprecated + ParameterBlocksUseRegisterSpaces, + + CountOfParsableOptions, + + // Used in parsed options only. + DebugInformationFormat, // intValue0: DebugInfoFormat + VulkanBindShiftAll, // intValue0: kind; intValue1: shift + GenerateWholeProgram, // bool + UseUpToDateBinaryModule, // bool, when set, will only load + // precompiled modules if it is up-to-date with its source. + EmbedDownstreamIR, // bool + ForceDXLayout, // bool + CountOf, + }; - enum class CompilerOptionValueKind - { - Int, - String - }; + enum class CompilerOptionValueKind + { + Int, + String + }; - struct CompilerOptionValue - { - CompilerOptionValueKind kind = CompilerOptionValueKind::Int; - int32_t intValue0 = 0; - int32_t intValue1 = 0; - const char* stringValue0 = nullptr; - const char* stringValue1 = nullptr; - }; + struct CompilerOptionValue + { + CompilerOptionValueKind kind = CompilerOptionValueKind::Int; + int32_t intValue0 = 0; + int32_t intValue1 = 0; + const char* stringValue0 = nullptr; + const char* stringValue1 = nullptr; + }; - struct CompilerOptionEntry - { - CompilerOptionName name; - CompilerOptionValue value; - }; - } + struct CompilerOptionEntry + { + CompilerOptionName name; + CompilerOptionValue value; + }; + } // namespace slang /** A result code for a Slang API operation. - This type is generally compatible with the Windows API `HRESULT` type. In particular, negative values indicate - failure results, while zero or positive results indicate success. + This type is generally compatible with the Windows API `HRESULT` type. In particular, negative + values indicate failure results, while zero or positive results indicate success. - In general, Slang APIs always return a zero result on success, unless documented otherwise. Strictly speaking - a negative value indicates an error, a positive (or 0) value indicates success. This can be tested for with the macros - SLANG_SUCCEEDED(x) or SLANG_FAILED(x). + In general, Slang APIs always return a zero result on success, unless documented otherwise. + Strictly speaking a negative value indicates an error, a positive (or 0) value indicates + success. This can be tested for with the macros SLANG_SUCCEEDED(x) or SLANG_FAILED(x). - It can represent if the call was successful or not. It can also specify in an extensible manner what facility - produced the result (as the integral 'facility') as well as what caused it (as an integral 'code'). - Under the covers SlangResult is represented as a int32_t. + It can represent if the call was successful or not. It can also specify in an extensible manner + what facility produced the result (as the integral 'facility') as well as what caused it (as an + integral 'code'). Under the covers SlangResult is represented as a int32_t. SlangResult is designed to be compatible with COM HRESULT. @@ -1016,8 +1037,9 @@ extern "C" ---------|----------|----- 31 | 30-16 | 15-0 - Severity - 1 fail, 0 is success - as SlangResult is signed 32 bits, means negative number indicates failure. - Facility is where the error originated from. Code is the code specific to the facility. + Severity - 1 fail, 0 is success - as SlangResult is signed 32 bits, means negative number + indicates failure. Facility is where the error originated from. Code is the code specific to the + facility. Result codes have the following styles, 1) SLANG_name @@ -1029,41 +1051,48 @@ extern "C" Style 1 is reserved for SLANG_OK and SLANG_FAIL as they are so commonly used. - It is acceptable to expand 'f' to a longer name to differentiate a name or drop if unique without it. - ie for a facility 'DRIVER' it might make sense to have an error of the form SLANG_E_DRIVER_OUT_OF_MEMORY + It is acceptable to expand 'f' to a longer name to differentiate a name or drop if unique + without it. ie for a facility 'DRIVER' it might make sense to have an error of the form + SLANG_E_DRIVER_OUT_OF_MEMORY */ typedef int32_t SlangResult; - //! Use to test if a result was failure. Never use result != SLANG_OK to test for failure, as there may be successful codes != SLANG_OK. + //! Use to test if a result was failure. Never use result != SLANG_OK to test for failure, as + //! there may be successful codes != SLANG_OK. #define SLANG_FAILED(status) ((status) < 0) - //! Use to test if a result succeeded. Never use result == SLANG_OK to test for success, as will detect other successful codes as a failure. + //! Use to test if a result succeeded. Never use result == SLANG_OK to test for success, as will + //! detect other successful codes as a failure. #define SLANG_SUCCEEDED(status) ((status) >= 0) //! Get the facility the result is associated with -#define SLANG_GET_RESULT_FACILITY(r) ((int32_t)(((r) >> 16) & 0x7fff)) +#define SLANG_GET_RESULT_FACILITY(r) ((int32_t)(((r) >> 16) & 0x7fff)) //! Get the result code for the facility -#define SLANG_GET_RESULT_CODE(r) ((int32_t)((r) & 0xffff)) +#define SLANG_GET_RESULT_CODE(r) ((int32_t)((r) & 0xffff)) -#define SLANG_MAKE_ERROR(fac, code) ((((int32_t)(fac)) << 16) | ((int32_t)(code)) | int32_t(0x80000000)) -#define SLANG_MAKE_SUCCESS(fac, code) ((((int32_t)(fac)) << 16) | ((int32_t)(code))) +#define SLANG_MAKE_ERROR(fac, code) \ + ((((int32_t)(fac)) << 16) | ((int32_t)(code)) | int32_t(0x80000000)) +#define SLANG_MAKE_SUCCESS(fac, code) ((((int32_t)(fac)) << 16) | ((int32_t)(code))) /*************************** Facilities ************************************/ //! Facilities compatible with windows COM - only use if known code is compatible -#define SLANG_FACILITY_WIN_GENERAL 0 -#define SLANG_FACILITY_WIN_INTERFACE 4 -#define SLANG_FACILITY_WIN_API 7 - - //! Base facility -> so as to not clash with HRESULT values (values in 0x200 range do not appear used) -#define SLANG_FACILITY_BASE 0x200 - - /*! Facilities numbers must be unique across a project to make the resulting result a unique number. - It can be useful to have a consistent short name for a facility, as used in the name prefix */ -#define SLANG_FACILITY_CORE SLANG_FACILITY_BASE - /* Facility for codes, that are not uniquely defined/protected. Can be used to pass back a specific error without requiring system wide facility uniqueness. Codes - should never be part of a public API. */ -#define SLANG_FACILITY_INTERNAL SLANG_FACILITY_BASE + 1 +#define SLANG_FACILITY_WIN_GENERAL 0 +#define SLANG_FACILITY_WIN_INTERFACE 4 +#define SLANG_FACILITY_WIN_API 7 + + //! Base facility -> so as to not clash with HRESULT values (values in 0x200 range do not appear + //! used) +#define SLANG_FACILITY_BASE 0x200 + + /*! Facilities numbers must be unique across a project to make the resulting result a unique + number. It can be useful to have a consistent short name for a facility, as used in the name + prefix */ +#define SLANG_FACILITY_CORE SLANG_FACILITY_BASE + /* Facility for codes, that are not uniquely defined/protected. Can be used to pass back a + specific error without requiring system wide facility uniqueness. Codes should never be part of + a public API. */ +#define SLANG_FACILITY_INTERNAL SLANG_FACILITY_BASE + 1 /// Base for external facilities. Facilities should be unique across modules. #define SLANG_FACILITY_EXTERNAL_BASE 0x210 @@ -1071,48 +1100,52 @@ extern "C" /* ************************ Win COM compatible Results ******************************/ // https://msdn.microsoft.com/en-us/library/windows/desktop/aa378137(v=vs.85).aspx - //! SLANG_OK indicates success, and is equivalent to SLANG_MAKE_SUCCESS(SLANG_FACILITY_WIN_GENERAL, 0) -#define SLANG_OK 0 - //! SLANG_FAIL is the generic failure code - meaning a serious error occurred and the call couldn't complete -#define SLANG_FAIL SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_GENERAL, 0x4005) + //! SLANG_OK indicates success, and is equivalent to + //! SLANG_MAKE_SUCCESS(SLANG_FACILITY_WIN_GENERAL, 0) +#define SLANG_OK 0 + //! SLANG_FAIL is the generic failure code - meaning a serious error occurred and the call + //! couldn't complete +#define SLANG_FAIL SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_GENERAL, 0x4005) -#define SLANG_MAKE_WIN_GENERAL_ERROR(code) SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_GENERAL, code) +#define SLANG_MAKE_WIN_GENERAL_ERROR(code) SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_GENERAL, code) //! Functionality is not implemented -#define SLANG_E_NOT_IMPLEMENTED SLANG_MAKE_WIN_GENERAL_ERROR(0x4001) +#define SLANG_E_NOT_IMPLEMENTED SLANG_MAKE_WIN_GENERAL_ERROR(0x4001) //! Interface not be found -#define SLANG_E_NO_INTERFACE SLANG_MAKE_WIN_GENERAL_ERROR(0x4002) +#define SLANG_E_NO_INTERFACE SLANG_MAKE_WIN_GENERAL_ERROR(0x4002) //! Operation was aborted (did not correctly complete) -#define SLANG_E_ABORT SLANG_MAKE_WIN_GENERAL_ERROR(0x4004) +#define SLANG_E_ABORT SLANG_MAKE_WIN_GENERAL_ERROR(0x4004) //! Indicates that a handle passed in as parameter to a method is invalid. -#define SLANG_E_INVALID_HANDLE SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_API, 6) +#define SLANG_E_INVALID_HANDLE SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_API, 6) //! Indicates that an argument passed in as parameter to a method is invalid. -#define SLANG_E_INVALID_ARG SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_API, 0x57) +#define SLANG_E_INVALID_ARG SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_API, 0x57) //! Operation could not complete - ran out of memory -#define SLANG_E_OUT_OF_MEMORY SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_API, 0xe) +#define SLANG_E_OUT_OF_MEMORY SLANG_MAKE_ERROR(SLANG_FACILITY_WIN_API, 0xe) /* *************************** other Results **************************************/ -#define SLANG_MAKE_CORE_ERROR(code) SLANG_MAKE_ERROR(SLANG_FACILITY_CORE, code) +#define SLANG_MAKE_CORE_ERROR(code) SLANG_MAKE_ERROR(SLANG_FACILITY_CORE, code) // Supplied buffer is too small to be able to complete -#define SLANG_E_BUFFER_TOO_SMALL SLANG_MAKE_CORE_ERROR(1) +#define SLANG_E_BUFFER_TOO_SMALL SLANG_MAKE_CORE_ERROR(1) //! Used to identify a Result that has yet to be initialized. - //! It defaults to failure such that if used incorrectly will fail, as similar in concept to using an uninitialized variable. -#define SLANG_E_UNINITIALIZED SLANG_MAKE_CORE_ERROR(2) - //! Returned from an async method meaning the output is invalid (thus an error), but a result for the request is pending, and will be returned on a subsequent call with the async handle. -#define SLANG_E_PENDING SLANG_MAKE_CORE_ERROR(3) + //! It defaults to failure such that if used incorrectly will fail, as similar in concept to + //! using an uninitialized variable. +#define SLANG_E_UNINITIALIZED SLANG_MAKE_CORE_ERROR(2) + //! Returned from an async method meaning the output is invalid (thus an error), but a result + //! for the request is pending, and will be returned on a subsequent call with the async handle. +#define SLANG_E_PENDING SLANG_MAKE_CORE_ERROR(3) //! Indicates a file/resource could not be opened -#define SLANG_E_CANNOT_OPEN SLANG_MAKE_CORE_ERROR(4) +#define SLANG_E_CANNOT_OPEN SLANG_MAKE_CORE_ERROR(4) //! Indicates a file/resource could not be found -#define SLANG_E_NOT_FOUND SLANG_MAKE_CORE_ERROR(5) +#define SLANG_E_NOT_FOUND SLANG_MAKE_CORE_ERROR(5) //! An unhandled internal failure (typically from unhandled exception) -#define SLANG_E_INTERNAL_FAIL SLANG_MAKE_CORE_ERROR(6) - //! Could not complete because some underlying feature (hardware or software) was not available -#define SLANG_E_NOT_AVAILABLE SLANG_MAKE_CORE_ERROR(7) - //! Could not complete because the operation times out. -#define SLANG_E_TIME_OUT SLANG_MAKE_CORE_ERROR(8) +#define SLANG_E_INTERNAL_FAIL SLANG_MAKE_CORE_ERROR(6) + //! Could not complete because some underlying feature (hardware or software) was not available +#define SLANG_E_NOT_AVAILABLE SLANG_MAKE_CORE_ERROR(7) + //! Could not complete because the operation times out. +#define SLANG_E_TIME_OUT SLANG_MAKE_CORE_ERROR(8) /** A "Universally Unique Identifier" (UUID) @@ -1128,40 +1161,47 @@ extern "C" uint32_t data1; uint16_t data2; uint16_t data3; - uint8_t data4[8]; + uint8_t data4[8]; }; // Place at the start of an interface with the guid. -// Guid should be specified as SLANG_COM_INTERFACE(0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }) -// NOTE: it's the typical guid struct definition, without the surrounding {} -// It is not necessary to use the multiple parameters (we can wrap in parens), but this is simple. +// Guid should be specified as SLANG_COM_INTERFACE(0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, +// 0x00, 0x00, 0x00, 0x00, 0x46 }) NOTE: it's the typical guid struct definition, without the +// surrounding {} It is not necessary to use the multiple parameters (we can wrap in parens), but +// this is simple. #define SLANG_COM_INTERFACE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ - public: \ - SLANG_FORCE_INLINE constexpr static SlangUUID getTypeGuid() \ - { \ - return { a, b, c, d0, d1, d2, d3, d4, d5, d6, d7 }; \ +public: \ + SLANG_FORCE_INLINE constexpr static SlangUUID getTypeGuid() \ + { \ + return {a, b, c, d0, d1, d2, d3, d4, d5, d6, d7}; \ } -// Sometimes it's useful to associate a guid with a class to identify it. This macro can used for this, -// and the guid extracted via the getTypeGuid() function defined in the type +// Sometimes it's useful to associate a guid with a class to identify it. This macro can used for +// this, and the guid extracted via the getTypeGuid() function defined in the type #define SLANG_CLASS_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ - SLANG_FORCE_INLINE constexpr static SlangUUID getTypeGuid() \ - { \ - return { a, b, c, d0, d1, d2, d3, d4, d5, d6, d7 }; \ + SLANG_FORCE_INLINE constexpr static SlangUUID getTypeGuid() \ + { \ + return {a, b, c, d0, d1, d2, d3, d4, d5, d6, d7}; \ } // Helper to fill in pairs of GUIDs and return pointers. This ensures that the // type of the GUID passed matches the pointer type, and that it is derived // from ISlangUnknown, -// TODO(c++20): would is_derived_from be more appropriate here for private inheritance of ISlangUnknown? +// TODO(c++20): would is_derived_from be more appropriate here for private inheritance of +// ISlangUnknown? // // with : void createFoo(SlangUUID, void**); // Slang::ComPtr myBar; // call with: createFoo(SLANG_IID_PPV_ARGS(myBar.writeRef())) // to call : createFoo(Bar::getTypeGuid(), (void**)(myBar.writeRef())) -#define SLANG_IID_PPV_ARGS(ppType) \ - std::decay_t::getTypeGuid(), \ - ((void)[]{static_assert(std::is_base_of_v>);}, reinterpret_cast(ppType)) +#define SLANG_IID_PPV_ARGS(ppType) \ + std::decay_t::getTypeGuid(), \ + ( \ + (void)[] { \ + static_assert( \ + std::is_base_of_v>); \ + }, \ + reinterpret_cast(ppType)) /** Base interface for components exchanged through the API. @@ -1172,9 +1212,14 @@ extern "C" */ struct ISlangUnknown { - SLANG_COM_INTERFACE(0x00000000, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }) + SLANG_COM_INTERFACE( + 0x00000000, + 0x0000, + 0x0000, + {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}) - virtual SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + queryInterface(SlangUUID const& uuid, void** outObject) = 0; virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() = 0; virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() = 0; @@ -1182,33 +1227,44 @@ extern "C" Inline methods are provided to allow the above operations to be called using their traditional COM names/signatures: */ - SlangResult QueryInterface(struct _GUID const& uuid, void** outObject) { return queryInterface(*(SlangUUID const*)&uuid, outObject); } + SlangResult QueryInterface(struct _GUID const& uuid, void** outObject) + { + return queryInterface(*(SlangUUID const*)&uuid, outObject); + } uint32_t AddRef() { return addRef(); } uint32_t Release() { return release(); } }; - #define SLANG_UUID_ISlangUnknown ISlangUnknown::getTypeGuid() +#define SLANG_UUID_ISlangUnknown ISlangUnknown::getTypeGuid() /* An interface to provide a mechanism to cast, that doesn't require ref counting and doesn't have to return a pointer to a ISlangUnknown derived class */ class ISlangCastable : public ISlangUnknown { - SLANG_COM_INTERFACE(0x87ede0e1, 0x4852, 0x44b0, { 0x8b, 0xf2, 0xcb, 0x31, 0x87, 0x4d, 0xe2, 0x39 }); - - /// Can be used to cast to interfaces without reference counting. - /// Also provides access to internal implementations, when they provide a guid - /// Can simulate a 'generated' interface as long as kept in scope by cast from. + SLANG_COM_INTERFACE( + 0x87ede0e1, + 0x4852, + 0x44b0, + {0x8b, 0xf2, 0xcb, 0x31, 0x87, 0x4d, 0xe2, 0x39}); + + /// Can be used to cast to interfaces without reference counting. + /// Also provides access to internal implementations, when they provide a guid + /// Can simulate a 'generated' interface as long as kept in scope by cast from. virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const SlangUUID& guid) = 0; }; class ISlangClonable : public ISlangCastable { - SLANG_COM_INTERFACE(0x1ec36168, 0xe9f4, 0x430d, { 0xbb, 0x17, 0x4, 0x8a, 0x80, 0x46, 0xb3, 0x1f }); - - /// Note the use of guid is for the desired interface/object. - /// The object is returned *not* ref counted. Any type that can implements the interface, - /// derives from ICastable, and so (not withstanding some other issue) will always return - /// an ICastable interface which other interfaces/types are accessible from via castAs + SLANG_COM_INTERFACE( + 0x1ec36168, + 0xe9f4, + 0x430d, + {0xbb, 0x17, 0x4, 0x8a, 0x80, 0x46, 0xb3, 0x1f}); + + /// Note the use of guid is for the desired interface/object. + /// The object is returned *not* ref counted. Any type that can implements the interface, + /// derives from ICastable, and so (not withstanding some other issue) will always return + /// an ICastable interface which other interfaces/types are accessible from via castAs SLANG_NO_THROW virtual void* SLANG_MCALL clone(const SlangUUID& guid) = 0; }; @@ -1218,18 +1274,27 @@ extern "C" */ struct ISlangBlob : public ISlangUnknown { - SLANG_COM_INTERFACE(0x8BA5FB08, 0x5195, 0x40e2, { 0xAC, 0x58, 0x0D, 0x98, 0x9C, 0x3A, 0x01, 0x02 }) + SLANG_COM_INTERFACE( + 0x8BA5FB08, + 0x5195, + 0x40e2, + {0xAC, 0x58, 0x0D, 0x98, 0x9C, 0x3A, 0x01, 0x02}) virtual SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() = 0; virtual SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() = 0; }; - #define SLANG_UUID_ISlangBlob ISlangBlob::getTypeGuid() +#define SLANG_UUID_ISlangBlob ISlangBlob::getTypeGuid() - /* Can be requested from ISlangCastable cast to indicate the contained chars are null terminated. - */ + /* Can be requested from ISlangCastable cast to indicate the contained chars are null + * terminated. + */ struct SlangTerminatedChars { - SLANG_CLASS_GUID(0xbe0db1a8, 0x3594, 0x4603, { 0xa7, 0x8b, 0xc4, 0x86, 0x84, 0x30, 0xdf, 0xbb }); + SLANG_CLASS_GUID( + 0xbe0db1a8, + 0x3594, + 0x4603, + {0xa7, 0x8b, 0xc4, 0x86, 0x84, 0x30, 0xdf, 0xbb}); operator const char*() const { return chars; } char chars[1]; }; @@ -1240,14 +1305,18 @@ extern "C" from disk, allowing applications to hook and/or override filesystem access from the compiler. - It is the responsibility of - the caller of any method that returns a ISlangBlob to release the blob when it is no + It is the responsibility of + the caller of any method that returns a ISlangBlob to release the blob when it is no longer used (using 'release'). */ struct ISlangFileSystem : public ISlangCastable { - SLANG_COM_INTERFACE(0x003A09FC, 0x3A4D, 0x4BA0, { 0xAD, 0x60, 0x1F, 0xD8, 0x63, 0xA9, 0x15, 0xAB }) + SLANG_COM_INTERFACE( + 0x003A09FC, + 0x3A4D, + 0x4BA0, + {0xAD, 0x60, 0x1F, 0xD8, 0x63, 0xA9, 0x15, 0xAB}) /** Load a file from `path` and return a blob of its contents @param path The path to load from, as a null-terminated UTF-8 string. @@ -1255,45 +1324,55 @@ extern "C" @returns A `SlangResult` to indicate success or failure in loading the file. NOTE! This is a *binary* load - the blob should contain the exact same bytes - as are found in the backing file. + as are found in the backing file. If load is successful, the implementation should create a blob to hold the file's content, store it to `outBlob`, and return 0. If the load fails, the implementation should return a failure status (any negative value will do). */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadFile( - char const* path, - ISlangBlob** outBlob) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + loadFile(char const* path, ISlangBlob** outBlob) = 0; }; - #define SLANG_UUID_ISlangFileSystem ISlangFileSystem::getTypeGuid() +#define SLANG_UUID_ISlangFileSystem ISlangFileSystem::getTypeGuid() - typedef void(*SlangFuncPtr)(void); + typedef void (*SlangFuncPtr)(void); - /** + /** (DEPRECATED) ISlangSharedLibrary */ - struct ISlangSharedLibrary_Dep1: public ISlangUnknown + struct ISlangSharedLibrary_Dep1 : public ISlangUnknown { - SLANG_COM_INTERFACE( 0x9c9d5bc5, 0xeb61, 0x496f,{ 0x80, 0xd7, 0xd1, 0x47, 0xc4, 0xa2, 0x37, 0x30 }) + SLANG_COM_INTERFACE( + 0x9c9d5bc5, + 0xeb61, + 0x496f, + {0x80, 0xd7, 0xd1, 0x47, 0xc4, 0xa2, 0x37, 0x30}) virtual SLANG_NO_THROW void* SLANG_MCALL findSymbolAddressByName(char const* name) = 0; }; - #define SLANG_UUID_ISlangSharedLibrary_Dep1 ISlangSharedLibrary_Dep1::getTypeGuid() +#define SLANG_UUID_ISlangSharedLibrary_Dep1 ISlangSharedLibrary_Dep1::getTypeGuid() /** An interface that can be used to encapsulate access to a shared library. An implementation does not have to implement the library as a shared library */ struct ISlangSharedLibrary : public ISlangCastable { - SLANG_COM_INTERFACE(0x70dbc7c4, 0xdc3b, 0x4a07, { 0xae, 0x7e, 0x75, 0x2a, 0xf6, 0xa8, 0x15, 0x55 }) + SLANG_COM_INTERFACE( + 0x70dbc7c4, + 0xdc3b, + 0x4a07, + {0xae, 0x7e, 0x75, 0x2a, 0xf6, 0xa8, 0x15, 0x55}) /** Get a function by name. If the library is unloaded will only return nullptr. @param name The name of the function @return The function pointer related to the name or nullptr if not found */ - SLANG_FORCE_INLINE SlangFuncPtr findFuncByName(char const* name) { return (SlangFuncPtr)findSymbolAddressByName(name); } + SLANG_FORCE_INLINE SlangFuncPtr findFuncByName(char const* name) + { + return (SlangFuncPtr)findSymbolAddressByName(name); + } /** Get a symbol by name. If the library is unloaded will only return nullptr. @param name The name of the symbol @@ -1301,166 +1380,183 @@ extern "C" */ virtual SLANG_NO_THROW void* SLANG_MCALL findSymbolAddressByName(char const* name) = 0; }; - #define SLANG_UUID_ISlangSharedLibrary ISlangSharedLibrary::getTypeGuid() +#define SLANG_UUID_ISlangSharedLibrary ISlangSharedLibrary::getTypeGuid() - struct ISlangSharedLibraryLoader: public ISlangUnknown + struct ISlangSharedLibraryLoader : public ISlangUnknown { - SLANG_COM_INTERFACE(0x6264ab2b, 0xa3e8, 0x4a06, { 0x97, 0xf1, 0x49, 0xbc, 0x2d, 0x2a, 0xb1, 0x4d }) - - /** Load a shared library. In typical usage the library name should *not* contain any platform - specific elements. For example on windows a dll name should *not* be passed with a '.dll' extension, - and similarly on linux a shared library should *not* be passed with the 'lib' prefix and '.so' extension - @path path The unadorned filename and/or path for the shared library - @ param sharedLibraryOut Holds the shared library if successfully loaded */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadSharedLibrary( - const char* path, - ISlangSharedLibrary** sharedLibraryOut) = 0; + SLANG_COM_INTERFACE( + 0x6264ab2b, + 0xa3e8, + 0x4a06, + {0x97, 0xf1, 0x49, 0xbc, 0x2d, 0x2a, 0xb1, 0x4d}) + + /** Load a shared library. In typical usage the library name should *not* contain any + platform specific elements. For example on windows a dll name should *not* be passed with a + '.dll' extension, and similarly on linux a shared library should *not* be passed with the + 'lib' prefix and '.so' extension + @path path The unadorned filename and/or path for the shared library + @ param sharedLibraryOut Holds the shared library if successfully loaded */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + loadSharedLibrary(const char* path, ISlangSharedLibrary** sharedLibraryOut) = 0; }; - #define SLANG_UUID_ISlangSharedLibraryLoader ISlangSharedLibraryLoader::getTypeGuid() - +#define SLANG_UUID_ISlangSharedLibraryLoader ISlangSharedLibraryLoader::getTypeGuid() + /* Type that identifies how a path should be interpreted */ typedef unsigned int SlangPathTypeIntegral; enum SlangPathType : SlangPathTypeIntegral { - SLANG_PATH_TYPE_DIRECTORY, /**< Path specified specifies a directory. */ - SLANG_PATH_TYPE_FILE, /**< Path specified is to a file. */ + SLANG_PATH_TYPE_DIRECTORY, /**< Path specified specifies a directory. */ + SLANG_PATH_TYPE_FILE, /**< Path specified is to a file. */ }; /* Callback to enumerate the contents of of a directory in a ISlangFileSystemExt. - The name is the name of a file system object (directory/file) in the specified path (ie it is without a path) */ - typedef void (*FileSystemContentsCallBack)(SlangPathType pathType, const char* name, void* userData); + The name is the name of a file system object (directory/file) in the specified path (ie it is + without a path) */ + typedef void ( + *FileSystemContentsCallBack)(SlangPathType pathType, const char* name, void* userData); /* Determines how paths map to files on the OS file system */ enum class OSPathKind : uint8_t { - None, ///< Paths do not map to the file system - Direct, ///< Paths map directly to the file system - OperatingSystem, ///< Only paths gained via PathKind::OperatingSystem map to the operating system file system + None, ///< Paths do not map to the file system + Direct, ///< Paths map directly to the file system + OperatingSystem, ///< Only paths gained via PathKind::OperatingSystem map to the operating + ///< system file system }; /* Used to determine what kind of path is required from an input path */ enum class PathKind { - /// Given a path, returns a simplified version of that path. - /// This typically means removing '..' and/or '.' from the path. - /// A simplified path must point to the same object as the original. - Simplified, - - /// Given a path, returns a 'canonical path' to the item. - /// This may be the operating system 'canonical path' that is the unique path to the item. - /// - /// If the item exists the returned canonical path should always be usable to access the item. - /// - /// If the item the path specifies doesn't exist, the canonical path may not be returnable - /// or be a path simplification. - /// Not all file systems support canonical paths. + /// Given a path, returns a simplified version of that path. + /// This typically means removing '..' and/or '.' from the path. + /// A simplified path must point to the same object as the original. + Simplified, + + /// Given a path, returns a 'canonical path' to the item. + /// This may be the operating system 'canonical path' that is the unique path to the item. + /// + /// If the item exists the returned canonical path should always be usable to access the + /// item. + /// + /// If the item the path specifies doesn't exist, the canonical path may not be returnable + /// or be a path simplification. + /// Not all file systems support canonical paths. Canonical, - /// Given a path returns a path such that it is suitable to be displayed to the user. - /// - /// For example if the file system is a zip file - it might include the path to the zip - /// container as well as the path to the specific file. - /// - /// NOTE! The display path won't necessarily work on the file system to access the item + /// Given a path returns a path such that it is suitable to be displayed to the user. + /// + /// For example if the file system is a zip file - it might include the path to the zip + /// container as well as the path to the specific file. + /// + /// NOTE! The display path won't necessarily work on the file system to access the item Display, - /// Get the path to the item on the *operating system* file system, if available. + /// Get the path to the item on the *operating system* file system, if available. OperatingSystem, CountOf, }; /** An extended file system abstraction. - - Implementing and using this interface over ISlangFileSystem gives much more control over how paths - are managed, as well as how it is determined if two files 'are the same'. + + Implementing and using this interface over ISlangFileSystem gives much more control over how + paths are managed, as well as how it is determined if two files 'are the same'. All paths as input char*, or output as ISlangBlobs are always encoded as UTF-8 strings. Blobs that contain strings are always zero terminated. */ struct ISlangFileSystemExt : public ISlangFileSystem { - SLANG_COM_INTERFACE(0x5fb632d2, 0x979d, 0x4481, { 0x9f, 0xee, 0x66, 0x3c, 0x3f, 0x14, 0x49, 0xe1 }) + SLANG_COM_INTERFACE( + 0x5fb632d2, + 0x979d, + 0x4481, + {0x9f, 0xee, 0x66, 0x3c, 0x3f, 0x14, 0x49, 0xe1}) /** Get a uniqueIdentity which uniquely identifies an object of the file system. - - Given a path, returns a 'uniqueIdentity' which ideally is the same value for the same object on the file system. - - The uniqueIdentity is used to compare if two paths are the same - which amongst other things allows Slang to - cache source contents internally. It is also used for #pragma once functionality. - - A *requirement* is for any implementation is that two paths can only return the same uniqueIdentity if the - contents of the two files are *identical*. If an implementation breaks this constraint it can produce incorrect compilation. - If an implementation cannot *strictly* identify *the same* files, this will only have an effect on #pragma once behavior. - - The string for the uniqueIdentity is held zero terminated in the ISlangBlob of outUniqueIdentity. - - Note that there are many ways a uniqueIdentity may be generated for a file. For example it could be the - 'canonical path' - assuming it is available and unambiguous for a file system. Another possible mechanism - could be to store the filename combined with the file date time to uniquely identify it. - + + Given a path, returns a 'uniqueIdentity' which ideally is the same value for the same object + on the file system. + + The uniqueIdentity is used to compare if two paths are the same - which amongst other things + allows Slang to cache source contents internally. It is also used for #pragma once + functionality. + + A *requirement* is for any implementation is that two paths can only return the same + uniqueIdentity if the contents of the two files are *identical*. If an implementation breaks + this constraint it can produce incorrect compilation. If an implementation cannot *strictly* + identify *the same* files, this will only have an effect on #pragma once behavior. + + The string for the uniqueIdentity is held zero terminated in the ISlangBlob of + outUniqueIdentity. + + Note that there are many ways a uniqueIdentity may be generated for a file. For example it + could be the 'canonical path' - assuming it is available and unambiguous for a file system. + Another possible mechanism could be to store the filename combined with the file date time + to uniquely identify it. + The client must ensure the blob be released when no longer used, otherwise memory will leak. - NOTE! Ideally this method would be called 'getPathUniqueIdentity' but for historical reasons and - backward compatibility it's name remains with 'File' even though an implementation should be made to work - with directories too. + NOTE! Ideally this method would be called 'getPathUniqueIdentity' but for historical reasons + and backward compatibility it's name remains with 'File' even though an implementation + should be made to work with directories too. @param path @param outUniqueIdentity @returns A `SlangResult` to indicate success or failure getting the uniqueIdentity. */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getFileUniqueIdentity( - const char* path, - ISlangBlob** outUniqueIdentity) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getFileUniqueIdentity(const char* path, ISlangBlob** outUniqueIdentity) = 0; /** Calculate a path combining the 'fromPath' with 'path' The client must ensure the blob be released when no longer used, otherwise memory will leak. @param fromPathType How to interpret the from path - as a file or a directory. - @param fromPath The from path. + @param fromPath The from path. @param path Path to be determined relative to the fromPath - @param pathOut Holds the string which is the relative path. The string is held in the blob zero terminated. + @param pathOut Holds the string which is the relative path. The string is held in the blob + zero terminated. @returns A `SlangResult` to indicate success or failure in loading the file. */ virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcCombinedPath( SlangPathType fromPathType, const char* fromPath, const char* path, - ISlangBlob** pathOut) = 0; - - /** Gets the type of path that path is on the file system. + ISlangBlob** pathOut) = 0; + + /** Gets the type of path that path is on the file system. @param path @param pathTypeOut - @returns SLANG_OK if located and type is known, else an error. SLANG_E_NOT_FOUND if not found. + @returns SLANG_OK if located and type is known, else an error. SLANG_E_NOT_FOUND if not + found. */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPathType( - const char* path, - SlangPathType* pathTypeOut) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getPathType(const char* path, SlangPathType* pathTypeOut) = 0; /** Get a path based on the kind. @param kind The kind of path wanted @param path The input path @param outPath The output path held in a blob - @returns SLANG_OK if successfully simplified the path (SLANG_E_NOT_IMPLEMENTED if not implemented, or some other error code) + @returns SLANG_OK if successfully simplified the path (SLANG_E_NOT_IMPLEMENTED if not + implemented, or some other error code) */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPath( - PathKind kind, - const char* path, - ISlangBlob** outPath) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getPath(PathKind kind, const char* path, ISlangBlob** outPath) = 0; /** Clears any cached information */ virtual SLANG_NO_THROW void SLANG_MCALL clearCache() = 0; /** Enumerate the contents of the path - - Note that for normal Slang operation it isn't necessary to enumerate contents this can return SLANG_E_NOT_IMPLEMENTED. - + + Note that for normal Slang operation it isn't necessary to enumerate contents this can + return SLANG_E_NOT_IMPLEMENTED. + @param The path to enumerate - @param callback This callback is called for each entry in the path. + @param callback This callback is called for each entry in the path. @param userData This is passed to the callback - @returns SLANG_OK if successful + @returns SLANG_OK if successful */ virtual SLANG_NO_THROW SlangResult SLANG_MCALL enumeratePathContents( const char* path, @@ -1468,67 +1564,69 @@ extern "C" void* userData) = 0; /** Returns how paths map to the OS file system - + @returns OSPathKind that describes how paths map to the Operating System file system */ virtual SLANG_NO_THROW OSPathKind SLANG_MCALL getOSPathKind() = 0; }; - #define SLANG_UUID_ISlangFileSystemExt ISlangFileSystemExt::getTypeGuid() +#define SLANG_UUID_ISlangFileSystemExt ISlangFileSystemExt::getTypeGuid() struct ISlangMutableFileSystem : public ISlangFileSystemExt { - SLANG_COM_INTERFACE(0xa058675c, 0x1d65, 0x452a, { 0x84, 0x58, 0xcc, 0xde, 0xd1, 0x42, 0x71, 0x5 }) + SLANG_COM_INTERFACE( + 0xa058675c, + 0x1d65, + 0x452a, + {0x84, 0x58, 0xcc, 0xde, 0xd1, 0x42, 0x71, 0x5}) /** Write data to the specified path. @param path The path for data to be saved to @param data The data to be saved @param size The size of the data in bytes - @returns SLANG_OK if successful (SLANG_E_NOT_IMPLEMENTED if not implemented, or some other error code) + @returns SLANG_OK if successful (SLANG_E_NOT_IMPLEMENTED if not implemented, or some other + error code) */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveFile( - const char* path, - const void* data, - size_t size) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + saveFile(const char* path, const void* data, size_t size) = 0; /** Write data in the form of a blob to the specified path. - Depending on the implementation writing a blob might be faster/use less memory. It is assumed the - blob is *immutable* and that an implementation can reference count it. + Depending on the implementation writing a blob might be faster/use less memory. It is + assumed the blob is *immutable* and that an implementation can reference count it. - It is not guaranteed loading the same file will return the *same* blob - just a blob with same - contents. + It is not guaranteed loading the same file will return the *same* blob - just a blob with + same contents. @param path The path for data to be saved to @param dataBlob The data to be saved - @returns SLANG_OK if successful (SLANG_E_NOT_IMPLEMENTED if not implemented, or some other error code) + @returns SLANG_OK if successful (SLANG_E_NOT_IMPLEMENTED if not implemented, or some other + error code) */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveFileBlob( - const char* path, - ISlangBlob* dataBlob) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + saveFileBlob(const char* path, ISlangBlob* dataBlob) = 0; - /** Remove the entry in the path (directory of file). Will only delete an empty directory, if not empty - will return an error. + /** Remove the entry in the path (directory of file). Will only delete an empty directory, + if not empty will return an error. - @param path The path to remove - @returns SLANG_OK if successful + @param path The path to remove + @returns SLANG_OK if successful */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL remove( - const char* path) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL remove(const char* path) = 0; /** Create a directory. The path to the directory must exist - @param path To the directory to create. The parent path *must* exist otherwise will return an error. - @returns SLANG_OK if successful + @param path To the directory to create. The parent path *must* exist otherwise will return + an error. + @returns SLANG_OK if successful */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createDirectory( - const char* path) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createDirectory(const char* path) = 0; }; - #define SLANG_UUID_ISlangMutableFileSystem ISlangMutableFileSystem::getTypeGuid() +#define SLANG_UUID_ISlangMutableFileSystem ISlangMutableFileSystem::getTypeGuid() /* Identifies different types of writer target*/ typedef unsigned int SlangWriterChannelIntegral; @@ -1548,51 +1646,64 @@ extern "C" }; /** A stream typically of text, used for outputting diagnostic as well as other information. - */ + */ struct ISlangWriter : public ISlangUnknown { - SLANG_COM_INTERFACE(0xec457f0e, 0x9add, 0x4e6b,{ 0x85, 0x1c, 0xd7, 0xfa, 0x71, 0x6d, 0x15, 0xfd }) - - /** Begin an append buffer. - NOTE! Only one append buffer can be active at any time. - @param maxNumChars The maximum of chars that will be appended - @returns The start of the buffer for appending to. */ + SLANG_COM_INTERFACE( + 0xec457f0e, + 0x9add, + 0x4e6b, + {0x85, 0x1c, 0xd7, 0xfa, 0x71, 0x6d, 0x15, 0xfd}) + + /** Begin an append buffer. + NOTE! Only one append buffer can be active at any time. + @param maxNumChars The maximum of chars that will be appended + @returns The start of the buffer for appending to. */ virtual SLANG_NO_THROW char* SLANG_MCALL beginAppendBuffer(size_t maxNumChars) = 0; - /** Ends the append buffer, and is equivalent to a write of the append buffer. - NOTE! That an endAppendBuffer is not necessary if there are no characters to write. - @param buffer is the start of the data to append and must be identical to last value returned from beginAppendBuffer - @param numChars must be a value less than or equal to what was returned from last call to beginAppendBuffer - @returns Result, will be SLANG_OK on success */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL endAppendBuffer(char* buffer, size_t numChars) = 0; - /** Write text to the writer - @param chars The characters to write out - @param numChars The amount of characters - @returns SLANG_OK on success */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL write(const char* chars, size_t numChars) = 0; - /** Flushes any content to the output */ + /** Ends the append buffer, and is equivalent to a write of the append buffer. + NOTE! That an endAppendBuffer is not necessary if there are no characters to write. + @param buffer is the start of the data to append and must be identical to last value + returned from beginAppendBuffer + @param numChars must be a value less than or equal to what was returned from last call to + beginAppendBuffer + @returns Result, will be SLANG_OK on success */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + endAppendBuffer(char* buffer, size_t numChars) = 0; + /** Write text to the writer + @param chars The characters to write out + @param numChars The amount of characters + @returns SLANG_OK on success */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + write(const char* chars, size_t numChars) = 0; + /** Flushes any content to the output */ virtual SLANG_NO_THROW void SLANG_MCALL flush() = 0; - /** Determines if the writer stream is to the console, and can be used to alter the output - @returns Returns true if is a console writer */ + /** Determines if the writer stream is to the console, and can be used to alter the output + @returns Returns true if is a console writer */ virtual SLANG_NO_THROW SlangBool SLANG_MCALL isConsole() = 0; - /** Set the mode for the writer to use - @param mode The mode to use - @returns SLANG_OK on success */ + /** Set the mode for the writer to use + @param mode The mode to use + @returns SLANG_OK on success */ virtual SLANG_NO_THROW SlangResult SLANG_MCALL setMode(SlangWriterMode mode) = 0; }; - - #define SLANG_UUID_ISlangWriter ISlangWriter::getTypeGuid() + +#define SLANG_UUID_ISlangWriter ISlangWriter::getTypeGuid() struct ISlangProfiler : public ISlangUnknown { - SLANG_COM_INTERFACE(0x197772c7, 0x0155, 0x4b91, { 0x84, 0xe8, 0x66, 0x68, 0xba, 0xff, 0x06, 0x19 }) + SLANG_COM_INTERFACE( + 0x197772c7, + 0x0155, + 0x4b91, + {0x84, 0xe8, 0x66, 0x68, 0xba, 0xff, 0x06, 0x19}) virtual SLANG_NO_THROW size_t SLANG_MCALL getEntryCount() = 0; virtual SLANG_NO_THROW const char* SLANG_MCALL getEntryName(uint32_t index) = 0; virtual SLANG_NO_THROW long SLANG_MCALL getEntryTimeMS(uint32_t index) = 0; virtual SLANG_NO_THROW uint32_t SLANG_MCALL getEntryInvocationTimes(uint32_t index) = 0; }; - #define SLANG_UUID_ISlangProfiler ISlangProfiler::getTypeGuid() +#define SLANG_UUID_ISlangProfiler ISlangProfiler::getTypeGuid() - namespace slang { + namespace slang + { struct IGlobalSession; struct ICompileRequest; @@ -1602,7 +1713,7 @@ extern "C" @brief An instance of the Slang library. */ typedef slang::IGlobalSession SlangSession; - + typedef struct SlangProgramLayout SlangProgramLayout; @@ -1612,12 +1723,10 @@ extern "C" typedef struct slang::ICompileRequest SlangCompileRequest; - /*! - @brief Callback type used for diagnostic output. - */ - typedef void(*SlangDiagnosticCallback)( - char const* message, - void* userData); + /*! +@brief Callback type used for diagnostic output. +*/ + typedef void (*SlangDiagnosticCallback)(char const* message, void* userData); /*! @brief Get the build version 'tag' string. The string is the same as @@ -1645,17 +1754,17 @@ extern "C" typedef struct SlangEntryPoint SlangEntryPoint; typedef struct SlangEntryPointLayout SlangEntryPointLayout; - typedef struct SlangReflectionDecl SlangReflectionDecl; - typedef struct SlangReflectionModifier SlangReflectionModifier; - typedef struct SlangReflectionType SlangReflectionType; - typedef struct SlangReflectionTypeLayout SlangReflectionTypeLayout; - typedef struct SlangReflectionVariable SlangReflectionVariable; - typedef struct SlangReflectionVariableLayout SlangReflectionVariableLayout; - typedef struct SlangReflectionTypeParameter SlangReflectionTypeParameter; - typedef struct SlangReflectionUserAttribute SlangReflectionUserAttribute; - typedef struct SlangReflectionFunction SlangReflectionFunction; - typedef struct SlangReflectionGeneric SlangReflectionGeneric; - + typedef struct SlangReflectionDecl SlangReflectionDecl; + typedef struct SlangReflectionModifier SlangReflectionModifier; + typedef struct SlangReflectionType SlangReflectionType; + typedef struct SlangReflectionTypeLayout SlangReflectionTypeLayout; + typedef struct SlangReflectionVariable SlangReflectionVariable; + typedef struct SlangReflectionVariableLayout SlangReflectionVariableLayout; + typedef struct SlangReflectionTypeParameter SlangReflectionTypeParameter; + typedef struct SlangReflectionUserAttribute SlangReflectionUserAttribute; + typedef struct SlangReflectionFunction SlangReflectionFunction; + typedef struct SlangReflectionGeneric SlangReflectionGeneric; + union SlangReflectionGenericArg { SlangReflectionType* typeVal; @@ -1739,40 +1848,41 @@ extern "C" }; #ifndef SLANG_RESOURCE_SHAPE -# define SLANG_RESOURCE_SHAPE + #define SLANG_RESOURCE_SHAPE typedef unsigned int SlangResourceShapeIntegral; enum SlangResourceShape : SlangResourceShapeIntegral { - SLANG_RESOURCE_BASE_SHAPE_MASK = 0x0F, + SLANG_RESOURCE_BASE_SHAPE_MASK = 0x0F, - SLANG_RESOURCE_NONE = 0x00, + SLANG_RESOURCE_NONE = 0x00, - SLANG_TEXTURE_1D = 0x01, - SLANG_TEXTURE_2D = 0x02, - SLANG_TEXTURE_3D = 0x03, - SLANG_TEXTURE_CUBE = 0x04, - SLANG_TEXTURE_BUFFER = 0x05, + SLANG_TEXTURE_1D = 0x01, + SLANG_TEXTURE_2D = 0x02, + SLANG_TEXTURE_3D = 0x03, + SLANG_TEXTURE_CUBE = 0x04, + SLANG_TEXTURE_BUFFER = 0x05, - SLANG_STRUCTURED_BUFFER = 0x06, - SLANG_BYTE_ADDRESS_BUFFER = 0x07, - SLANG_RESOURCE_UNKNOWN = 0x08, - SLANG_ACCELERATION_STRUCTURE = 0x09, - SLANG_TEXTURE_SUBPASS = 0x0A, + SLANG_STRUCTURED_BUFFER = 0x06, + SLANG_BYTE_ADDRESS_BUFFER = 0x07, + SLANG_RESOURCE_UNKNOWN = 0x08, + SLANG_ACCELERATION_STRUCTURE = 0x09, + SLANG_TEXTURE_SUBPASS = 0x0A, - SLANG_RESOURCE_EXT_SHAPE_MASK = 0xF0, + SLANG_RESOURCE_EXT_SHAPE_MASK = 0xF0, - SLANG_TEXTURE_FEEDBACK_FLAG = 0x10, - SLANG_TEXTURE_SHADOW_FLAG = 0x20, - SLANG_TEXTURE_ARRAY_FLAG = 0x40, - SLANG_TEXTURE_MULTISAMPLE_FLAG = 0x80, + SLANG_TEXTURE_FEEDBACK_FLAG = 0x10, + SLANG_TEXTURE_SHADOW_FLAG = 0x20, + SLANG_TEXTURE_ARRAY_FLAG = 0x40, + SLANG_TEXTURE_MULTISAMPLE_FLAG = 0x80, - SLANG_TEXTURE_1D_ARRAY = SLANG_TEXTURE_1D | SLANG_TEXTURE_ARRAY_FLAG, - SLANG_TEXTURE_2D_ARRAY = SLANG_TEXTURE_2D | SLANG_TEXTURE_ARRAY_FLAG, - SLANG_TEXTURE_CUBE_ARRAY = SLANG_TEXTURE_CUBE | SLANG_TEXTURE_ARRAY_FLAG, + SLANG_TEXTURE_1D_ARRAY = SLANG_TEXTURE_1D | SLANG_TEXTURE_ARRAY_FLAG, + SLANG_TEXTURE_2D_ARRAY = SLANG_TEXTURE_2D | SLANG_TEXTURE_ARRAY_FLAG, + SLANG_TEXTURE_CUBE_ARRAY = SLANG_TEXTURE_CUBE | SLANG_TEXTURE_ARRAY_FLAG, - SLANG_TEXTURE_2D_MULTISAMPLE = SLANG_TEXTURE_2D | SLANG_TEXTURE_MULTISAMPLE_FLAG, - SLANG_TEXTURE_2D_MULTISAMPLE_ARRAY = SLANG_TEXTURE_2D | SLANG_TEXTURE_MULTISAMPLE_FLAG | SLANG_TEXTURE_ARRAY_FLAG, - SLANG_TEXTURE_SUBPASS_MULTISAMPLE = SLANG_TEXTURE_SUBPASS | SLANG_TEXTURE_MULTISAMPLE_FLAG, + SLANG_TEXTURE_2D_MULTISAMPLE = SLANG_TEXTURE_2D | SLANG_TEXTURE_MULTISAMPLE_FLAG, + SLANG_TEXTURE_2D_MULTISAMPLE_ARRAY = + SLANG_TEXTURE_2D | SLANG_TEXTURE_MULTISAMPLE_FLAG | SLANG_TEXTURE_ARRAY_FLAG, + SLANG_TEXTURE_SUBPASS_MULTISAMPLE = SLANG_TEXTURE_SUBPASS | SLANG_TEXTURE_MULTISAMPLE_FLAG, }; #endif typedef unsigned int SlangResourceAccessIntegral; @@ -1888,7 +1998,7 @@ extern "C" }; /** Types of API-managed bindings that a parameter might use. - + `SlangBindingType` represents the distinct types of binding ranges that might be understood by an underlying graphics API or cross-API abstraction layer. Several of the enumeration cases here correspond to cases of `VkDescriptorType` @@ -1934,12 +2044,15 @@ extern "C" SLANG_BINDING_TYPE_MUTABLE_FLAG = 0x100, - SLANG_BINDING_TYPE_MUTABLE_TETURE = SLANG_BINDING_TYPE_TEXTURE | SLANG_BINDING_TYPE_MUTABLE_FLAG, - SLANG_BINDING_TYPE_MUTABLE_TYPED_BUFFER = SLANG_BINDING_TYPE_TYPED_BUFFER | SLANG_BINDING_TYPE_MUTABLE_FLAG, - SLANG_BINDING_TYPE_MUTABLE_RAW_BUFFER = SLANG_BINDING_TYPE_RAW_BUFFER | SLANG_BINDING_TYPE_MUTABLE_FLAG, + SLANG_BINDING_TYPE_MUTABLE_TETURE = + SLANG_BINDING_TYPE_TEXTURE | SLANG_BINDING_TYPE_MUTABLE_FLAG, + SLANG_BINDING_TYPE_MUTABLE_TYPED_BUFFER = + SLANG_BINDING_TYPE_TYPED_BUFFER | SLANG_BINDING_TYPE_MUTABLE_FLAG, + SLANG_BINDING_TYPE_MUTABLE_RAW_BUFFER = + SLANG_BINDING_TYPE_RAW_BUFFER | SLANG_BINDING_TYPE_MUTABLE_FLAG, SLANG_BINDING_TYPE_BASE_MASK = 0x00FF, - SLANG_BINDING_TYPE_EXT_MASK = 0xFF00, + SLANG_BINDING_TYPE_EXT_MASK = 0xFF00, }; typedef SlangUInt32 SlangLayoutRulesIntegral; @@ -1973,7 +2086,7 @@ extern "C" #undef SLANG_FORMAT }; - #define SLANG_UNBOUNDED_SIZE (~size_t(0)) +#define SLANG_UNBOUNDED_SIZE (~size_t(0)) // Shader Parameter Reflection @@ -1986,7 +2099,7 @@ extern "C" #ifdef __cplusplus namespace slang { - struct ISession; +struct ISession; } #endif @@ -1997,2249 +2110,2264 @@ namespace slang /* Helper interfaces for C++ users */ namespace slang { - struct BufferReflection; - struct DeclReflection; - struct TypeLayoutReflection; - struct TypeReflection; - struct VariableLayoutReflection; - struct VariableReflection; - struct FunctionReflection; - struct GenericReflection; - - union GenericArgReflection - { - TypeReflection* typeVal; - int64_t intVal; - bool boolVal; - }; - - struct UserAttribute +struct BufferReflection; +struct DeclReflection; +struct TypeLayoutReflection; +struct TypeReflection; +struct VariableLayoutReflection; +struct VariableReflection; +struct FunctionReflection; +struct GenericReflection; + +union GenericArgReflection +{ + TypeReflection* typeVal; + int64_t intVal; + bool boolVal; +}; + +struct UserAttribute +{ + char const* getName() { - char const* getName() - { - return spReflectionUserAttribute_GetName((SlangReflectionUserAttribute*)this); - } - uint32_t getArgumentCount() - { - return (uint32_t)spReflectionUserAttribute_GetArgumentCount((SlangReflectionUserAttribute*)this); - } - TypeReflection* getArgumentType(uint32_t index) - { - return (TypeReflection*)spReflectionUserAttribute_GetArgumentType((SlangReflectionUserAttribute*)this, index); - } - SlangResult getArgumentValueInt(uint32_t index, int * value) - { - return spReflectionUserAttribute_GetArgumentValueInt((SlangReflectionUserAttribute*)this, index, value); - } - SlangResult getArgumentValueFloat(uint32_t index, float * value) - { - return spReflectionUserAttribute_GetArgumentValueFloat((SlangReflectionUserAttribute*)this, index, value); - } - const char* getArgumentValueString(uint32_t index, size_t * outSize) - { - return spReflectionUserAttribute_GetArgumentValueString((SlangReflectionUserAttribute*)this, index, outSize); - } - }; + return spReflectionUserAttribute_GetName((SlangReflectionUserAttribute*)this); + } + uint32_t getArgumentCount() + { + return (uint32_t)spReflectionUserAttribute_GetArgumentCount( + (SlangReflectionUserAttribute*)this); + } + TypeReflection* getArgumentType(uint32_t index) + { + return (TypeReflection*)spReflectionUserAttribute_GetArgumentType( + (SlangReflectionUserAttribute*)this, + index); + } + SlangResult getArgumentValueInt(uint32_t index, int* value) + { + return spReflectionUserAttribute_GetArgumentValueInt( + (SlangReflectionUserAttribute*)this, + index, + value); + } + SlangResult getArgumentValueFloat(uint32_t index, float* value) + { + return spReflectionUserAttribute_GetArgumentValueFloat( + (SlangReflectionUserAttribute*)this, + index, + value); + } + const char* getArgumentValueString(uint32_t index, size_t* outSize) + { + return spReflectionUserAttribute_GetArgumentValueString( + (SlangReflectionUserAttribute*)this, + index, + outSize); + } +}; - struct TypeReflection +struct TypeReflection +{ + enum class Kind { - enum class Kind - { - None = SLANG_TYPE_KIND_NONE, - Struct = SLANG_TYPE_KIND_STRUCT, - Array = SLANG_TYPE_KIND_ARRAY, - Matrix = SLANG_TYPE_KIND_MATRIX, - Vector = SLANG_TYPE_KIND_VECTOR, - Scalar = SLANG_TYPE_KIND_SCALAR, - ConstantBuffer = SLANG_TYPE_KIND_CONSTANT_BUFFER, - Resource = SLANG_TYPE_KIND_RESOURCE, - SamplerState = SLANG_TYPE_KIND_SAMPLER_STATE, - TextureBuffer = SLANG_TYPE_KIND_TEXTURE_BUFFER, - ShaderStorageBuffer = SLANG_TYPE_KIND_SHADER_STORAGE_BUFFER, - ParameterBlock = SLANG_TYPE_KIND_PARAMETER_BLOCK, - GenericTypeParameter = SLANG_TYPE_KIND_GENERIC_TYPE_PARAMETER, - Interface = SLANG_TYPE_KIND_INTERFACE, - OutputStream = SLANG_TYPE_KIND_OUTPUT_STREAM, - Specialized = SLANG_TYPE_KIND_SPECIALIZED, - Feedback = SLANG_TYPE_KIND_FEEDBACK, - Pointer = SLANG_TYPE_KIND_POINTER, - DynamicResource = SLANG_TYPE_KIND_DYNAMIC_RESOURCE, - }; + None = SLANG_TYPE_KIND_NONE, + Struct = SLANG_TYPE_KIND_STRUCT, + Array = SLANG_TYPE_KIND_ARRAY, + Matrix = SLANG_TYPE_KIND_MATRIX, + Vector = SLANG_TYPE_KIND_VECTOR, + Scalar = SLANG_TYPE_KIND_SCALAR, + ConstantBuffer = SLANG_TYPE_KIND_CONSTANT_BUFFER, + Resource = SLANG_TYPE_KIND_RESOURCE, + SamplerState = SLANG_TYPE_KIND_SAMPLER_STATE, + TextureBuffer = SLANG_TYPE_KIND_TEXTURE_BUFFER, + ShaderStorageBuffer = SLANG_TYPE_KIND_SHADER_STORAGE_BUFFER, + ParameterBlock = SLANG_TYPE_KIND_PARAMETER_BLOCK, + GenericTypeParameter = SLANG_TYPE_KIND_GENERIC_TYPE_PARAMETER, + Interface = SLANG_TYPE_KIND_INTERFACE, + OutputStream = SLANG_TYPE_KIND_OUTPUT_STREAM, + Specialized = SLANG_TYPE_KIND_SPECIALIZED, + Feedback = SLANG_TYPE_KIND_FEEDBACK, + Pointer = SLANG_TYPE_KIND_POINTER, + DynamicResource = SLANG_TYPE_KIND_DYNAMIC_RESOURCE, + }; - enum ScalarType : SlangScalarTypeIntegral - { - None = SLANG_SCALAR_TYPE_NONE, - Void = SLANG_SCALAR_TYPE_VOID, - Bool = SLANG_SCALAR_TYPE_BOOL, - Int32 = SLANG_SCALAR_TYPE_INT32, - UInt32 = SLANG_SCALAR_TYPE_UINT32, - Int64 = SLANG_SCALAR_TYPE_INT64, - UInt64 = SLANG_SCALAR_TYPE_UINT64, - Float16 = SLANG_SCALAR_TYPE_FLOAT16, - Float32 = SLANG_SCALAR_TYPE_FLOAT32, - Float64 = SLANG_SCALAR_TYPE_FLOAT64, - Int8 = SLANG_SCALAR_TYPE_INT8, - UInt8 = SLANG_SCALAR_TYPE_UINT8, - Int16 = SLANG_SCALAR_TYPE_INT16, - UInt16 = SLANG_SCALAR_TYPE_UINT16, - }; + enum ScalarType : SlangScalarTypeIntegral + { + None = SLANG_SCALAR_TYPE_NONE, + Void = SLANG_SCALAR_TYPE_VOID, + Bool = SLANG_SCALAR_TYPE_BOOL, + Int32 = SLANG_SCALAR_TYPE_INT32, + UInt32 = SLANG_SCALAR_TYPE_UINT32, + Int64 = SLANG_SCALAR_TYPE_INT64, + UInt64 = SLANG_SCALAR_TYPE_UINT64, + Float16 = SLANG_SCALAR_TYPE_FLOAT16, + Float32 = SLANG_SCALAR_TYPE_FLOAT32, + Float64 = SLANG_SCALAR_TYPE_FLOAT64, + Int8 = SLANG_SCALAR_TYPE_INT8, + UInt8 = SLANG_SCALAR_TYPE_UINT8, + Int16 = SLANG_SCALAR_TYPE_INT16, + UInt16 = SLANG_SCALAR_TYPE_UINT16, + }; - Kind getKind() - { - return (Kind) spReflectionType_GetKind((SlangReflectionType*) this); - } + Kind getKind() { return (Kind)spReflectionType_GetKind((SlangReflectionType*)this); } - // only useful if `getKind() == Kind::Struct` - unsigned int getFieldCount() - { - return spReflectionType_GetFieldCount((SlangReflectionType*) this); - } + // only useful if `getKind() == Kind::Struct` + unsigned int getFieldCount() + { + return spReflectionType_GetFieldCount((SlangReflectionType*)this); + } - VariableReflection* getFieldByIndex(unsigned int index) - { - return (VariableReflection*) spReflectionType_GetFieldByIndex((SlangReflectionType*) this, index); - } + VariableReflection* getFieldByIndex(unsigned int index) + { + return ( + VariableReflection*)spReflectionType_GetFieldByIndex((SlangReflectionType*)this, index); + } - bool isArray() { return getKind() == TypeReflection::Kind::Array; } + bool isArray() { return getKind() == TypeReflection::Kind::Array; } - TypeReflection* unwrapArray() + TypeReflection* unwrapArray() + { + TypeReflection* type = this; + while (type->isArray()) { - TypeReflection* type = this; - while( type->isArray() ) - { - type = type->getElementType(); - } - return type; + type = type->getElementType(); } + return type; + } - // only useful if `getKind() == Kind::Array` - size_t getElementCount() - { - return spReflectionType_GetElementCount((SlangReflectionType*) this); - } + // only useful if `getKind() == Kind::Array` + size_t getElementCount() + { + return spReflectionType_GetElementCount((SlangReflectionType*)this); + } - size_t getTotalArrayElementCount() + size_t getTotalArrayElementCount() + { + if (!isArray()) + return 0; + size_t result = 1; + TypeReflection* type = this; + for (;;) { - if(!isArray()) return 0; - size_t result = 1; - TypeReflection* type = this; - for(;;) - { - if(!type->isArray()) - return result; + if (!type->isArray()) + return result; - result *= type->getElementCount(); - type = type->getElementType(); - } + result *= type->getElementCount(); + type = type->getElementType(); } + } - TypeReflection* getElementType() - { - return (TypeReflection*) spReflectionType_GetElementType((SlangReflectionType*) this); - } + TypeReflection* getElementType() + { + return (TypeReflection*)spReflectionType_GetElementType((SlangReflectionType*)this); + } - unsigned getRowCount() - { - return spReflectionType_GetRowCount((SlangReflectionType*) this); - } + unsigned getRowCount() { return spReflectionType_GetRowCount((SlangReflectionType*)this); } - unsigned getColumnCount() - { - return spReflectionType_GetColumnCount((SlangReflectionType*) this); - } + unsigned getColumnCount() + { + return spReflectionType_GetColumnCount((SlangReflectionType*)this); + } - ScalarType getScalarType() - { - return (ScalarType) spReflectionType_GetScalarType((SlangReflectionType*) this); - } + ScalarType getScalarType() + { + return (ScalarType)spReflectionType_GetScalarType((SlangReflectionType*)this); + } - TypeReflection* getResourceResultType() - { - return (TypeReflection*) spReflectionType_GetResourceResultType((SlangReflectionType*) this); - } + TypeReflection* getResourceResultType() + { + return (TypeReflection*)spReflectionType_GetResourceResultType((SlangReflectionType*)this); + } - SlangResourceShape getResourceShape() - { - return spReflectionType_GetResourceShape((SlangReflectionType*) this); - } + SlangResourceShape getResourceShape() + { + return spReflectionType_GetResourceShape((SlangReflectionType*)this); + } - SlangResourceAccess getResourceAccess() - { - return spReflectionType_GetResourceAccess((SlangReflectionType*) this); - } + SlangResourceAccess getResourceAccess() + { + return spReflectionType_GetResourceAccess((SlangReflectionType*)this); + } - char const* getName() - { - return spReflectionType_GetName((SlangReflectionType*) this); - } + char const* getName() { return spReflectionType_GetName((SlangReflectionType*)this); } - SlangResult getFullName(ISlangBlob** outNameBlob) - { - return spReflectionType_GetFullName((SlangReflectionType*)this, outNameBlob); - } + SlangResult getFullName(ISlangBlob** outNameBlob) + { + return spReflectionType_GetFullName((SlangReflectionType*)this, outNameBlob); + } - unsigned int getUserAttributeCount() - { - return spReflectionType_GetUserAttributeCount((SlangReflectionType*)this); - } + unsigned int getUserAttributeCount() + { + return spReflectionType_GetUserAttributeCount((SlangReflectionType*)this); + } - UserAttribute* getUserAttributeByIndex(unsigned int index) - { - return (UserAttribute*)spReflectionType_GetUserAttribute((SlangReflectionType*)this, index); - } + UserAttribute* getUserAttributeByIndex(unsigned int index) + { + return (UserAttribute*)spReflectionType_GetUserAttribute((SlangReflectionType*)this, index); + } - UserAttribute* findUserAttributeByName(char const* name) - { - return (UserAttribute*)spReflectionType_FindUserAttributeByName((SlangReflectionType*)this, name); - } + UserAttribute* findUserAttributeByName(char const* name) + { + return (UserAttribute*)spReflectionType_FindUserAttributeByName( + (SlangReflectionType*)this, + name); + } - TypeReflection* applySpecializations(GenericReflection* generic) - { - return (TypeReflection*)spReflectionType_applySpecializations((SlangReflectionType*)this, (SlangReflectionGeneric*)generic); - } + TypeReflection* applySpecializations(GenericReflection* generic) + { + return (TypeReflection*)spReflectionType_applySpecializations( + (SlangReflectionType*)this, + (SlangReflectionGeneric*)generic); + } - GenericReflection* getGenericContainer() - { - return (GenericReflection*) spReflectionType_GetGenericContainer((SlangReflectionType*) this); - } - }; + GenericReflection* getGenericContainer() + { + return (GenericReflection*)spReflectionType_GetGenericContainer((SlangReflectionType*)this); + } +}; + +enum ParameterCategory : SlangParameterCategoryIntegral +{ + // TODO: these aren't scoped... + None = SLANG_PARAMETER_CATEGORY_NONE, + Mixed = SLANG_PARAMETER_CATEGORY_MIXED, + ConstantBuffer = SLANG_PARAMETER_CATEGORY_CONSTANT_BUFFER, + ShaderResource = SLANG_PARAMETER_CATEGORY_SHADER_RESOURCE, + UnorderedAccess = SLANG_PARAMETER_CATEGORY_UNORDERED_ACCESS, + VaryingInput = SLANG_PARAMETER_CATEGORY_VARYING_INPUT, + VaryingOutput = SLANG_PARAMETER_CATEGORY_VARYING_OUTPUT, + SamplerState = SLANG_PARAMETER_CATEGORY_SAMPLER_STATE, + Uniform = SLANG_PARAMETER_CATEGORY_UNIFORM, + DescriptorTableSlot = SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT, + SpecializationConstant = SLANG_PARAMETER_CATEGORY_SPECIALIZATION_CONSTANT, + PushConstantBuffer = SLANG_PARAMETER_CATEGORY_PUSH_CONSTANT_BUFFER, + RegisterSpace = SLANG_PARAMETER_CATEGORY_REGISTER_SPACE, + GenericResource = SLANG_PARAMETER_CATEGORY_GENERIC, + + RayPayload = SLANG_PARAMETER_CATEGORY_RAY_PAYLOAD, + HitAttributes = SLANG_PARAMETER_CATEGORY_HIT_ATTRIBUTES, + CallablePayload = SLANG_PARAMETER_CATEGORY_CALLABLE_PAYLOAD, + + ShaderRecord = SLANG_PARAMETER_CATEGORY_SHADER_RECORD, + + ExistentialTypeParam = SLANG_PARAMETER_CATEGORY_EXISTENTIAL_TYPE_PARAM, + ExistentialObjectParam = SLANG_PARAMETER_CATEGORY_EXISTENTIAL_OBJECT_PARAM, + + SubElementRegisterSpace = SLANG_PARAMETER_CATEGORY_SUB_ELEMENT_REGISTER_SPACE, + + InputAttachmentIndex = SLANG_PARAMETER_CATEGORY_SUBPASS, + + MetalBuffer = SLANG_PARAMETER_CATEGORY_CONSTANT_BUFFER, + MetalTexture = SLANG_PARAMETER_CATEGORY_METAL_TEXTURE, + MetalArgumentBufferElement = SLANG_PARAMETER_CATEGORY_METAL_ARGUMENT_BUFFER_ELEMENT, + MetalAttribute = SLANG_PARAMETER_CATEGORY_METAL_ATTRIBUTE, + MetalPayload = SLANG_PARAMETER_CATEGORY_METAL_PAYLOAD, + + // DEPRECATED: + VertexInput = SLANG_PARAMETER_CATEGORY_VERTEX_INPUT, + FragmentOutput = SLANG_PARAMETER_CATEGORY_FRAGMENT_OUTPUT, +}; + +enum class BindingType : SlangBindingTypeIntegral +{ + Unknown = SLANG_BINDING_TYPE_UNKNOWN, + + Sampler = SLANG_BINDING_TYPE_SAMPLER, + Texture = SLANG_BINDING_TYPE_TEXTURE, + ConstantBuffer = SLANG_BINDING_TYPE_CONSTANT_BUFFER, + ParameterBlock = SLANG_BINDING_TYPE_PARAMETER_BLOCK, + TypedBuffer = SLANG_BINDING_TYPE_TYPED_BUFFER, + RawBuffer = SLANG_BINDING_TYPE_RAW_BUFFER, + CombinedTextureSampler = SLANG_BINDING_TYPE_COMBINED_TEXTURE_SAMPLER, + InputRenderTarget = SLANG_BINDING_TYPE_INPUT_RENDER_TARGET, + InlineUniformData = SLANG_BINDING_TYPE_INLINE_UNIFORM_DATA, + RayTracingAccelerationStructure = SLANG_BINDING_TYPE_RAY_TRACING_ACCELERATION_STRUCTURE, + VaryingInput = SLANG_BINDING_TYPE_VARYING_INPUT, + VaryingOutput = SLANG_BINDING_TYPE_VARYING_OUTPUT, + ExistentialValue = SLANG_BINDING_TYPE_EXISTENTIAL_VALUE, + PushConstant = SLANG_BINDING_TYPE_PUSH_CONSTANT, + + MutableFlag = SLANG_BINDING_TYPE_MUTABLE_FLAG, + + MutableTexture = SLANG_BINDING_TYPE_MUTABLE_TETURE, + MutableTypedBuffer = SLANG_BINDING_TYPE_MUTABLE_TYPED_BUFFER, + MutableRawBuffer = SLANG_BINDING_TYPE_MUTABLE_RAW_BUFFER, + + BaseMask = SLANG_BINDING_TYPE_BASE_MASK, + ExtMask = SLANG_BINDING_TYPE_EXT_MASK, +}; + +struct TypeLayoutReflection +{ + TypeReflection* getType() + { + return (TypeReflection*)spReflectionTypeLayout_GetType((SlangReflectionTypeLayout*)this); + } - enum ParameterCategory : SlangParameterCategoryIntegral + TypeReflection::Kind getKind() { - // TODO: these aren't scoped... - None = SLANG_PARAMETER_CATEGORY_NONE, - Mixed = SLANG_PARAMETER_CATEGORY_MIXED, - ConstantBuffer = SLANG_PARAMETER_CATEGORY_CONSTANT_BUFFER, - ShaderResource = SLANG_PARAMETER_CATEGORY_SHADER_RESOURCE, - UnorderedAccess = SLANG_PARAMETER_CATEGORY_UNORDERED_ACCESS, - VaryingInput = SLANG_PARAMETER_CATEGORY_VARYING_INPUT, - VaryingOutput = SLANG_PARAMETER_CATEGORY_VARYING_OUTPUT, - SamplerState = SLANG_PARAMETER_CATEGORY_SAMPLER_STATE, - Uniform = SLANG_PARAMETER_CATEGORY_UNIFORM, - DescriptorTableSlot = SLANG_PARAMETER_CATEGORY_DESCRIPTOR_TABLE_SLOT, - SpecializationConstant = SLANG_PARAMETER_CATEGORY_SPECIALIZATION_CONSTANT, - PushConstantBuffer = SLANG_PARAMETER_CATEGORY_PUSH_CONSTANT_BUFFER, - RegisterSpace = SLANG_PARAMETER_CATEGORY_REGISTER_SPACE, - GenericResource = SLANG_PARAMETER_CATEGORY_GENERIC, + return (TypeReflection::Kind)spReflectionTypeLayout_getKind( + (SlangReflectionTypeLayout*)this); + } - RayPayload = SLANG_PARAMETER_CATEGORY_RAY_PAYLOAD, - HitAttributes = SLANG_PARAMETER_CATEGORY_HIT_ATTRIBUTES, - CallablePayload = SLANG_PARAMETER_CATEGORY_CALLABLE_PAYLOAD, + size_t getSize(SlangParameterCategory category = SLANG_PARAMETER_CATEGORY_UNIFORM) + { + return spReflectionTypeLayout_GetSize((SlangReflectionTypeLayout*)this, category); + } - ShaderRecord = SLANG_PARAMETER_CATEGORY_SHADER_RECORD, + size_t getStride(SlangParameterCategory category = SLANG_PARAMETER_CATEGORY_UNIFORM) + { + return spReflectionTypeLayout_GetStride((SlangReflectionTypeLayout*)this, category); + } - ExistentialTypeParam = SLANG_PARAMETER_CATEGORY_EXISTENTIAL_TYPE_PARAM, - ExistentialObjectParam = SLANG_PARAMETER_CATEGORY_EXISTENTIAL_OBJECT_PARAM, + int32_t getAlignment(SlangParameterCategory category = SLANG_PARAMETER_CATEGORY_UNIFORM) + { + return spReflectionTypeLayout_getAlignment((SlangReflectionTypeLayout*)this, category); + } - SubElementRegisterSpace = SLANG_PARAMETER_CATEGORY_SUB_ELEMENT_REGISTER_SPACE, + unsigned int getFieldCount() + { + return spReflectionTypeLayout_GetFieldCount((SlangReflectionTypeLayout*)this); + } - InputAttachmentIndex = SLANG_PARAMETER_CATEGORY_SUBPASS, + VariableLayoutReflection* getFieldByIndex(unsigned int index) + { + return (VariableLayoutReflection*)spReflectionTypeLayout_GetFieldByIndex( + (SlangReflectionTypeLayout*)this, + index); + } - MetalBuffer = SLANG_PARAMETER_CATEGORY_CONSTANT_BUFFER, - MetalTexture = SLANG_PARAMETER_CATEGORY_METAL_TEXTURE, - MetalArgumentBufferElement = SLANG_PARAMETER_CATEGORY_METAL_ARGUMENT_BUFFER_ELEMENT, - MetalAttribute = SLANG_PARAMETER_CATEGORY_METAL_ATTRIBUTE, - MetalPayload = SLANG_PARAMETER_CATEGORY_METAL_PAYLOAD, + SlangInt findFieldIndexByName(char const* nameBegin, char const* nameEnd = nullptr) + { + return spReflectionTypeLayout_findFieldIndexByName( + (SlangReflectionTypeLayout*)this, + nameBegin, + nameEnd); + } - // DEPRECATED: - VertexInput = SLANG_PARAMETER_CATEGORY_VERTEX_INPUT, - FragmentOutput = SLANG_PARAMETER_CATEGORY_FRAGMENT_OUTPUT, - }; + VariableLayoutReflection* getExplicitCounter() + { + return (VariableLayoutReflection*)spReflectionTypeLayout_GetExplicitCounter( + (SlangReflectionTypeLayout*)this); + } - enum class BindingType : SlangBindingTypeIntegral - { - Unknown = SLANG_BINDING_TYPE_UNKNOWN, - - Sampler = SLANG_BINDING_TYPE_SAMPLER, - Texture = SLANG_BINDING_TYPE_TEXTURE, - ConstantBuffer = SLANG_BINDING_TYPE_CONSTANT_BUFFER, - ParameterBlock = SLANG_BINDING_TYPE_PARAMETER_BLOCK, - TypedBuffer = SLANG_BINDING_TYPE_TYPED_BUFFER, - RawBuffer = SLANG_BINDING_TYPE_RAW_BUFFER, - CombinedTextureSampler = SLANG_BINDING_TYPE_COMBINED_TEXTURE_SAMPLER, - InputRenderTarget = SLANG_BINDING_TYPE_INPUT_RENDER_TARGET, - InlineUniformData = SLANG_BINDING_TYPE_INLINE_UNIFORM_DATA, - RayTracingAccelerationStructure = SLANG_BINDING_TYPE_RAY_TRACING_ACCELERATION_STRUCTURE, - VaryingInput = SLANG_BINDING_TYPE_VARYING_INPUT, - VaryingOutput = SLANG_BINDING_TYPE_VARYING_OUTPUT, - ExistentialValue = SLANG_BINDING_TYPE_EXISTENTIAL_VALUE, - PushConstant = SLANG_BINDING_TYPE_PUSH_CONSTANT, - - MutableFlag = SLANG_BINDING_TYPE_MUTABLE_FLAG, - - MutableTexture = SLANG_BINDING_TYPE_MUTABLE_TETURE, - MutableTypedBuffer = SLANG_BINDING_TYPE_MUTABLE_TYPED_BUFFER, - MutableRawBuffer = SLANG_BINDING_TYPE_MUTABLE_RAW_BUFFER, - - BaseMask = SLANG_BINDING_TYPE_BASE_MASK, - ExtMask = SLANG_BINDING_TYPE_EXT_MASK, - }; + bool isArray() { return getType()->isArray(); } - struct TypeLayoutReflection + TypeLayoutReflection* unwrapArray() { - TypeReflection* getType() + TypeLayoutReflection* typeLayout = this; + while (typeLayout->isArray()) { - return (TypeReflection*) spReflectionTypeLayout_GetType((SlangReflectionTypeLayout*) this); + typeLayout = typeLayout->getElementTypeLayout(); } + return typeLayout; + } - TypeReflection::Kind getKind() - { - return (TypeReflection::Kind) spReflectionTypeLayout_getKind((SlangReflectionTypeLayout*) this); - } + // only useful if `getKind() == Kind::Array` + size_t getElementCount() { return getType()->getElementCount(); } - size_t getSize(SlangParameterCategory category = SLANG_PARAMETER_CATEGORY_UNIFORM) - { - return spReflectionTypeLayout_GetSize((SlangReflectionTypeLayout*) this, category); - } + size_t getTotalArrayElementCount() { return getType()->getTotalArrayElementCount(); } - size_t getStride(SlangParameterCategory category = SLANG_PARAMETER_CATEGORY_UNIFORM) - { - return spReflectionTypeLayout_GetStride((SlangReflectionTypeLayout*) this, category); - } + size_t getElementStride(SlangParameterCategory category) + { + return spReflectionTypeLayout_GetElementStride((SlangReflectionTypeLayout*)this, category); + } - int32_t getAlignment(SlangParameterCategory category = SLANG_PARAMETER_CATEGORY_UNIFORM) - { - return spReflectionTypeLayout_getAlignment((SlangReflectionTypeLayout*) this, category); - } + TypeLayoutReflection* getElementTypeLayout() + { + return (TypeLayoutReflection*)spReflectionTypeLayout_GetElementTypeLayout( + (SlangReflectionTypeLayout*)this); + } - unsigned int getFieldCount() - { - return spReflectionTypeLayout_GetFieldCount((SlangReflectionTypeLayout*)this); - } + VariableLayoutReflection* getElementVarLayout() + { + return (VariableLayoutReflection*)spReflectionTypeLayout_GetElementVarLayout( + (SlangReflectionTypeLayout*)this); + } - VariableLayoutReflection* getFieldByIndex(unsigned int index) - { - return (VariableLayoutReflection*) spReflectionTypeLayout_GetFieldByIndex((SlangReflectionTypeLayout*) this, index); - } + VariableLayoutReflection* getContainerVarLayout() + { + return (VariableLayoutReflection*)spReflectionTypeLayout_getContainerVarLayout( + (SlangReflectionTypeLayout*)this); + } - SlangInt findFieldIndexByName(char const* nameBegin, char const* nameEnd = nullptr) - { - return spReflectionTypeLayout_findFieldIndexByName((SlangReflectionTypeLayout*) this, nameBegin, nameEnd); - } + // How is this type supposed to be bound? + ParameterCategory getParameterCategory() + { + return (ParameterCategory)spReflectionTypeLayout_GetParameterCategory( + (SlangReflectionTypeLayout*)this); + } - VariableLayoutReflection* getExplicitCounter() - { - return (VariableLayoutReflection*) spReflectionTypeLayout_GetExplicitCounter((SlangReflectionTypeLayout*) this); - } + unsigned int getCategoryCount() + { + return spReflectionTypeLayout_GetCategoryCount((SlangReflectionTypeLayout*)this); + } - bool isArray() { return getType()->isArray(); } + ParameterCategory getCategoryByIndex(unsigned int index) + { + return (ParameterCategory)spReflectionTypeLayout_GetCategoryByIndex( + (SlangReflectionTypeLayout*)this, + index); + } - TypeLayoutReflection* unwrapArray() - { - TypeLayoutReflection* typeLayout = this; - while( typeLayout->isArray() ) - { - typeLayout = typeLayout->getElementTypeLayout(); - } - return typeLayout; - } + unsigned getRowCount() { return getType()->getRowCount(); } - // only useful if `getKind() == Kind::Array` - size_t getElementCount() - { - return getType()->getElementCount(); - } + unsigned getColumnCount() { return getType()->getColumnCount(); } - size_t getTotalArrayElementCount() - { - return getType()->getTotalArrayElementCount(); - } + TypeReflection::ScalarType getScalarType() { return getType()->getScalarType(); } - size_t getElementStride(SlangParameterCategory category) - { - return spReflectionTypeLayout_GetElementStride((SlangReflectionTypeLayout*) this, category); - } + TypeReflection* getResourceResultType() { return getType()->getResourceResultType(); } - TypeLayoutReflection* getElementTypeLayout() - { - return (TypeLayoutReflection*) spReflectionTypeLayout_GetElementTypeLayout((SlangReflectionTypeLayout*) this); - } + SlangResourceShape getResourceShape() { return getType()->getResourceShape(); } - VariableLayoutReflection* getElementVarLayout() - { - return (VariableLayoutReflection*)spReflectionTypeLayout_GetElementVarLayout((SlangReflectionTypeLayout*) this); - } + SlangResourceAccess getResourceAccess() { return getType()->getResourceAccess(); } - VariableLayoutReflection* getContainerVarLayout() - { - return (VariableLayoutReflection*)spReflectionTypeLayout_getContainerVarLayout((SlangReflectionTypeLayout*) this); - } + char const* getName() { return getType()->getName(); } - // How is this type supposed to be bound? - ParameterCategory getParameterCategory() - { - return (ParameterCategory) spReflectionTypeLayout_GetParameterCategory((SlangReflectionTypeLayout*) this); - } + SlangMatrixLayoutMode getMatrixLayoutMode() + { + return spReflectionTypeLayout_GetMatrixLayoutMode((SlangReflectionTypeLayout*)this); + } - unsigned int getCategoryCount() - { - return spReflectionTypeLayout_GetCategoryCount((SlangReflectionTypeLayout*) this); - } + int getGenericParamIndex() + { + return spReflectionTypeLayout_getGenericParamIndex((SlangReflectionTypeLayout*)this); + } - ParameterCategory getCategoryByIndex(unsigned int index) - { - return (ParameterCategory) spReflectionTypeLayout_GetCategoryByIndex((SlangReflectionTypeLayout*) this, index); - } + TypeLayoutReflection* getPendingDataTypeLayout() + { + return (TypeLayoutReflection*)spReflectionTypeLayout_getPendingDataTypeLayout( + (SlangReflectionTypeLayout*)this); + } - unsigned getRowCount() - { - return getType()->getRowCount(); - } + VariableLayoutReflection* getSpecializedTypePendingDataVarLayout() + { + return (VariableLayoutReflection*) + spReflectionTypeLayout_getSpecializedTypePendingDataVarLayout( + (SlangReflectionTypeLayout*)this); + } - unsigned getColumnCount() - { - return getType()->getColumnCount(); - } + SlangInt getBindingRangeCount() + { + return spReflectionTypeLayout_getBindingRangeCount((SlangReflectionTypeLayout*)this); + } - TypeReflection::ScalarType getScalarType() - { - return getType()->getScalarType(); - } + BindingType getBindingRangeType(SlangInt index) + { + return (BindingType)spReflectionTypeLayout_getBindingRangeType( + (SlangReflectionTypeLayout*)this, + index); + } - TypeReflection* getResourceResultType() - { - return getType()->getResourceResultType(); - } + bool isBindingRangeSpecializable(SlangInt index) + { + return (bool)spReflectionTypeLayout_isBindingRangeSpecializable( + (SlangReflectionTypeLayout*)this, + index); + } - SlangResourceShape getResourceShape() - { - return getType()->getResourceShape(); - } + SlangInt getBindingRangeBindingCount(SlangInt index) + { + return spReflectionTypeLayout_getBindingRangeBindingCount( + (SlangReflectionTypeLayout*)this, + index); + } - SlangResourceAccess getResourceAccess() - { - return getType()->getResourceAccess(); - } + /* + SlangInt getBindingRangeIndexOffset(SlangInt index) + { + return spReflectionTypeLayout_getBindingRangeIndexOffset( + (SlangReflectionTypeLayout*) this, + index); + } - char const* getName() - { - return getType()->getName(); - } + SlangInt getBindingRangeSpaceOffset(SlangInt index) + { + return spReflectionTypeLayout_getBindingRangeSpaceOffset( + (SlangReflectionTypeLayout*) this, + index); + } + */ - SlangMatrixLayoutMode getMatrixLayoutMode() - { - return spReflectionTypeLayout_GetMatrixLayoutMode((SlangReflectionTypeLayout*) this); - } + SlangInt getFieldBindingRangeOffset(SlangInt fieldIndex) + { + return spReflectionTypeLayout_getFieldBindingRangeOffset( + (SlangReflectionTypeLayout*)this, + fieldIndex); + } - int getGenericParamIndex() - { - return spReflectionTypeLayout_getGenericParamIndex( - (SlangReflectionTypeLayout*) this); - } + SlangInt getExplicitCounterBindingRangeOffset() + { + return spReflectionTypeLayout_getExplicitCounterBindingRangeOffset( + (SlangReflectionTypeLayout*)this); + } - TypeLayoutReflection* getPendingDataTypeLayout() - { - return (TypeLayoutReflection*) spReflectionTypeLayout_getPendingDataTypeLayout( - (SlangReflectionTypeLayout*) this); - } + TypeLayoutReflection* getBindingRangeLeafTypeLayout(SlangInt index) + { + return (TypeLayoutReflection*)spReflectionTypeLayout_getBindingRangeLeafTypeLayout( + (SlangReflectionTypeLayout*)this, + index); + } - VariableLayoutReflection* getSpecializedTypePendingDataVarLayout() - { - return (VariableLayoutReflection*) spReflectionTypeLayout_getSpecializedTypePendingDataVarLayout( - (SlangReflectionTypeLayout*) this); - } + VariableReflection* getBindingRangeLeafVariable(SlangInt index) + { + return (VariableReflection*)spReflectionTypeLayout_getBindingRangeLeafVariable( + (SlangReflectionTypeLayout*)this, + index); + } - SlangInt getBindingRangeCount() - { - return spReflectionTypeLayout_getBindingRangeCount( - (SlangReflectionTypeLayout*) this); - } + SlangImageFormat getBindingRangeImageFormat(SlangInt index) + { + return spReflectionTypeLayout_getBindingRangeImageFormat( + (SlangReflectionTypeLayout*)this, + index); + } - BindingType getBindingRangeType(SlangInt index) - { - return (BindingType) spReflectionTypeLayout_getBindingRangeType( - (SlangReflectionTypeLayout*) this, - index); - } + SlangInt getBindingRangeDescriptorSetIndex(SlangInt index) + { + return spReflectionTypeLayout_getBindingRangeDescriptorSetIndex( + (SlangReflectionTypeLayout*)this, + index); + } - bool isBindingRangeSpecializable(SlangInt index) - { - return (bool)spReflectionTypeLayout_isBindingRangeSpecializable( - (SlangReflectionTypeLayout*)this, - index); + SlangInt getBindingRangeFirstDescriptorRangeIndex(SlangInt index) + { + return spReflectionTypeLayout_getBindingRangeFirstDescriptorRangeIndex( + (SlangReflectionTypeLayout*)this, + index); + } - } + SlangInt getBindingRangeDescriptorRangeCount(SlangInt index) + { + return spReflectionTypeLayout_getBindingRangeDescriptorRangeCount( + (SlangReflectionTypeLayout*)this, + index); + } - SlangInt getBindingRangeBindingCount(SlangInt index) - { - return spReflectionTypeLayout_getBindingRangeBindingCount( - (SlangReflectionTypeLayout*) this, - index); - } + SlangInt getDescriptorSetCount() + { + return spReflectionTypeLayout_getDescriptorSetCount((SlangReflectionTypeLayout*)this); + } - /* - SlangInt getBindingRangeIndexOffset(SlangInt index) - { - return spReflectionTypeLayout_getBindingRangeIndexOffset( - (SlangReflectionTypeLayout*) this, - index); - } + SlangInt getDescriptorSetSpaceOffset(SlangInt setIndex) + { + return spReflectionTypeLayout_getDescriptorSetSpaceOffset( + (SlangReflectionTypeLayout*)this, + setIndex); + } - SlangInt getBindingRangeSpaceOffset(SlangInt index) - { - return spReflectionTypeLayout_getBindingRangeSpaceOffset( - (SlangReflectionTypeLayout*) this, - index); - } - */ + SlangInt getDescriptorSetDescriptorRangeCount(SlangInt setIndex) + { + return spReflectionTypeLayout_getDescriptorSetDescriptorRangeCount( + (SlangReflectionTypeLayout*)this, + setIndex); + } - SlangInt getFieldBindingRangeOffset(SlangInt fieldIndex) - { - return spReflectionTypeLayout_getFieldBindingRangeOffset( - (SlangReflectionTypeLayout*) this, - fieldIndex); - } + SlangInt getDescriptorSetDescriptorRangeIndexOffset(SlangInt setIndex, SlangInt rangeIndex) + { + return spReflectionTypeLayout_getDescriptorSetDescriptorRangeIndexOffset( + (SlangReflectionTypeLayout*)this, + setIndex, + rangeIndex); + } - SlangInt getExplicitCounterBindingRangeOffset() - { - return spReflectionTypeLayout_getExplicitCounterBindingRangeOffset( - (SlangReflectionTypeLayout*) this); - } + SlangInt getDescriptorSetDescriptorRangeDescriptorCount(SlangInt setIndex, SlangInt rangeIndex) + { + return spReflectionTypeLayout_getDescriptorSetDescriptorRangeDescriptorCount( + (SlangReflectionTypeLayout*)this, + setIndex, + rangeIndex); + } - TypeLayoutReflection* getBindingRangeLeafTypeLayout(SlangInt index) - { - return (TypeLayoutReflection*) spReflectionTypeLayout_getBindingRangeLeafTypeLayout( - (SlangReflectionTypeLayout*) this, - index); - } + BindingType getDescriptorSetDescriptorRangeType(SlangInt setIndex, SlangInt rangeIndex) + { + return (BindingType)spReflectionTypeLayout_getDescriptorSetDescriptorRangeType( + (SlangReflectionTypeLayout*)this, + setIndex, + rangeIndex); + } - VariableReflection* getBindingRangeLeafVariable(SlangInt index) - { - return (VariableReflection*)spReflectionTypeLayout_getBindingRangeLeafVariable( - (SlangReflectionTypeLayout*)this, index); - } + ParameterCategory getDescriptorSetDescriptorRangeCategory( + SlangInt setIndex, + SlangInt rangeIndex) + { + return (ParameterCategory)spReflectionTypeLayout_getDescriptorSetDescriptorRangeCategory( + (SlangReflectionTypeLayout*)this, + setIndex, + rangeIndex); + } - SlangImageFormat getBindingRangeImageFormat(SlangInt index) - { - return spReflectionTypeLayout_getBindingRangeImageFormat( - (SlangReflectionTypeLayout*)this, index); - } + SlangInt getSubObjectRangeCount() + { + return spReflectionTypeLayout_getSubObjectRangeCount((SlangReflectionTypeLayout*)this); + } - SlangInt getBindingRangeDescriptorSetIndex(SlangInt index) - { - return spReflectionTypeLayout_getBindingRangeDescriptorSetIndex( - (SlangReflectionTypeLayout*) this, - index); - } + SlangInt getSubObjectRangeBindingRangeIndex(SlangInt subObjectRangeIndex) + { + return spReflectionTypeLayout_getSubObjectRangeBindingRangeIndex( + (SlangReflectionTypeLayout*)this, + subObjectRangeIndex); + } - SlangInt getBindingRangeFirstDescriptorRangeIndex(SlangInt index) - { - return spReflectionTypeLayout_getBindingRangeFirstDescriptorRangeIndex( - (SlangReflectionTypeLayout*) this, - index); - } + SlangInt getSubObjectRangeSpaceOffset(SlangInt subObjectRangeIndex) + { + return spReflectionTypeLayout_getSubObjectRangeSpaceOffset( + (SlangReflectionTypeLayout*)this, + subObjectRangeIndex); + } - SlangInt getBindingRangeDescriptorRangeCount(SlangInt index) - { - return spReflectionTypeLayout_getBindingRangeDescriptorRangeCount( - (SlangReflectionTypeLayout*) this, - index); - } + VariableLayoutReflection* getSubObjectRangeOffset(SlangInt subObjectRangeIndex) + { + return (VariableLayoutReflection*)spReflectionTypeLayout_getSubObjectRangeOffset( + (SlangReflectionTypeLayout*)this, + subObjectRangeIndex); + } +}; - SlangInt getDescriptorSetCount() - { - return spReflectionTypeLayout_getDescriptorSetCount( - (SlangReflectionTypeLayout*) this); - } +struct Modifier +{ + enum ID : SlangModifierIDIntegral + { + Shared = SLANG_MODIFIER_SHARED, + NoDiff = SLANG_MODIFIER_NO_DIFF, + Static = SLANG_MODIFIER_STATIC, + Const = SLANG_MODIFIER_CONST, + Export = SLANG_MODIFIER_EXPORT, + Extern = SLANG_MODIFIER_EXTERN, + Differentiable = SLANG_MODIFIER_DIFFERENTIABLE, + Mutating = SLANG_MODIFIER_MUTATING, + In = SLANG_MODIFIER_IN, + Out = SLANG_MODIFIER_OUT, + InOut = SLANG_MODIFIER_INOUT + }; +}; - SlangInt getDescriptorSetSpaceOffset(SlangInt setIndex) - { - return spReflectionTypeLayout_getDescriptorSetSpaceOffset( - (SlangReflectionTypeLayout*) this, - setIndex); - } +struct VariableReflection +{ + char const* getName() { return spReflectionVariable_GetName((SlangReflectionVariable*)this); } - SlangInt getDescriptorSetDescriptorRangeCount(SlangInt setIndex) - { - return spReflectionTypeLayout_getDescriptorSetDescriptorRangeCount( - (SlangReflectionTypeLayout*) this, - setIndex); - } + TypeReflection* getType() + { + return (TypeReflection*)spReflectionVariable_GetType((SlangReflectionVariable*)this); + } - SlangInt getDescriptorSetDescriptorRangeIndexOffset(SlangInt setIndex, SlangInt rangeIndex) - { - return spReflectionTypeLayout_getDescriptorSetDescriptorRangeIndexOffset( - (SlangReflectionTypeLayout*) this, - setIndex, - rangeIndex); - } + Modifier* findModifier(Modifier::ID id) + { + return (Modifier*)spReflectionVariable_FindModifier( + (SlangReflectionVariable*)this, + (SlangModifierID)id); + } - SlangInt getDescriptorSetDescriptorRangeDescriptorCount(SlangInt setIndex, SlangInt rangeIndex) - { - return spReflectionTypeLayout_getDescriptorSetDescriptorRangeDescriptorCount( - (SlangReflectionTypeLayout*) this, - setIndex, - rangeIndex); - } + unsigned int getUserAttributeCount() + { + return spReflectionVariable_GetUserAttributeCount((SlangReflectionVariable*)this); + } - BindingType getDescriptorSetDescriptorRangeType(SlangInt setIndex, SlangInt rangeIndex) - { - return (BindingType) spReflectionTypeLayout_getDescriptorSetDescriptorRangeType( - (SlangReflectionTypeLayout*) this, - setIndex, - rangeIndex); - } + UserAttribute* getUserAttributeByIndex(unsigned int index) + { + return (UserAttribute*)spReflectionVariable_GetUserAttribute( + (SlangReflectionVariable*)this, + index); + } - ParameterCategory getDescriptorSetDescriptorRangeCategory(SlangInt setIndex, SlangInt rangeIndex) - { - return (ParameterCategory) spReflectionTypeLayout_getDescriptorSetDescriptorRangeCategory( - (SlangReflectionTypeLayout*) this, - setIndex, - rangeIndex); - } + UserAttribute* findUserAttributeByName(SlangSession* globalSession, char const* name) + { + return (UserAttribute*)spReflectionVariable_FindUserAttributeByName( + (SlangReflectionVariable*)this, + globalSession, + name); + } - SlangInt getSubObjectRangeCount() - { - return spReflectionTypeLayout_getSubObjectRangeCount( - (SlangReflectionTypeLayout*) this); - } + bool hasDefaultValue() + { + return spReflectionVariable_HasDefaultValue((SlangReflectionVariable*)this); + } - SlangInt getSubObjectRangeBindingRangeIndex(SlangInt subObjectRangeIndex) - { - return spReflectionTypeLayout_getSubObjectRangeBindingRangeIndex( - (SlangReflectionTypeLayout*) this, - subObjectRangeIndex); - } + GenericReflection* getGenericContainer() + { + return (GenericReflection*)spReflectionVariable_GetGenericContainer( + (SlangReflectionVariable*)this); + } - SlangInt getSubObjectRangeSpaceOffset(SlangInt subObjectRangeIndex) - { - return spReflectionTypeLayout_getSubObjectRangeSpaceOffset( - (SlangReflectionTypeLayout*) this, - subObjectRangeIndex); - } + VariableReflection* applySpecializations(GenericReflection* generic) + { + return (VariableReflection*)spReflectionVariable_applySpecializations( + (SlangReflectionVariable*)this, + (SlangReflectionGeneric*)generic); + } +}; - VariableLayoutReflection* getSubObjectRangeOffset(SlangInt subObjectRangeIndex) - { - return (VariableLayoutReflection*) spReflectionTypeLayout_getSubObjectRangeOffset( - (SlangReflectionTypeLayout*) this, - subObjectRangeIndex); - } - }; +struct VariableLayoutReflection +{ + VariableReflection* getVariable() + { + return (VariableReflection*)spReflectionVariableLayout_GetVariable( + (SlangReflectionVariableLayout*)this); + } + + char const* getName() { return getVariable()->getName(); } - struct Modifier + Modifier* findModifier(Modifier::ID id) { return getVariable()->findModifier(id); } + + TypeLayoutReflection* getTypeLayout() { - enum ID : SlangModifierIDIntegral - { - Shared = SLANG_MODIFIER_SHARED, - NoDiff = SLANG_MODIFIER_NO_DIFF, - Static = SLANG_MODIFIER_STATIC, - Const = SLANG_MODIFIER_CONST, - Export = SLANG_MODIFIER_EXPORT, - Extern = SLANG_MODIFIER_EXTERN, - Differentiable = SLANG_MODIFIER_DIFFERENTIABLE, - Mutating = SLANG_MODIFIER_MUTATING, - In = SLANG_MODIFIER_IN, - Out = SLANG_MODIFIER_OUT, - InOut = SLANG_MODIFIER_INOUT - }; - }; + return (TypeLayoutReflection*)spReflectionVariableLayout_GetTypeLayout( + (SlangReflectionVariableLayout*)this); + } + + ParameterCategory getCategory() { return getTypeLayout()->getParameterCategory(); } - struct VariableReflection + unsigned int getCategoryCount() { return getTypeLayout()->getCategoryCount(); } + + ParameterCategory getCategoryByIndex(unsigned int index) { - char const* getName() - { - return spReflectionVariable_GetName((SlangReflectionVariable*) this); - } + return getTypeLayout()->getCategoryByIndex(index); + } - TypeReflection* getType() - { - return (TypeReflection*) spReflectionVariable_GetType((SlangReflectionVariable*) this); - } - Modifier* findModifier(Modifier::ID id) - { - return (Modifier*) spReflectionVariable_FindModifier((SlangReflectionVariable*) this, (SlangModifierID) id); - } + size_t getOffset(SlangParameterCategory category = SLANG_PARAMETER_CATEGORY_UNIFORM) + { + return spReflectionVariableLayout_GetOffset((SlangReflectionVariableLayout*)this, category); + } - unsigned int getUserAttributeCount() - { - return spReflectionVariable_GetUserAttributeCount((SlangReflectionVariable*)this); - } + TypeReflection* getType() { return getVariable()->getType(); } - UserAttribute* getUserAttributeByIndex(unsigned int index) - { - return (UserAttribute*)spReflectionVariable_GetUserAttribute((SlangReflectionVariable*)this, index); - } + unsigned getBindingIndex() + { + return spReflectionParameter_GetBindingIndex((SlangReflectionVariableLayout*)this); + } - UserAttribute* findUserAttributeByName(SlangSession* globalSession, char const* name) - { - return (UserAttribute*)spReflectionVariable_FindUserAttributeByName((SlangReflectionVariable*)this, globalSession, name); - } + unsigned getBindingSpace() + { + return spReflectionParameter_GetBindingSpace((SlangReflectionVariableLayout*)this); + } - bool hasDefaultValue() - { - return spReflectionVariable_HasDefaultValue((SlangReflectionVariable*)this); - } + size_t getBindingSpace(SlangParameterCategory category) + { + return spReflectionVariableLayout_GetSpace((SlangReflectionVariableLayout*)this, category); + } - GenericReflection* getGenericContainer() - { - return (GenericReflection*)spReflectionVariable_GetGenericContainer((SlangReflectionVariable*)this); - } + char const* getSemanticName() + { + return spReflectionVariableLayout_GetSemanticName((SlangReflectionVariableLayout*)this); + } - VariableReflection* applySpecializations(GenericReflection* generic) - { - return (VariableReflection*)spReflectionVariable_applySpecializations((SlangReflectionVariable*)this, (SlangReflectionGeneric*)generic); - } - }; + size_t getSemanticIndex() + { + return spReflectionVariableLayout_GetSemanticIndex((SlangReflectionVariableLayout*)this); + } - struct VariableLayoutReflection + SlangStage getStage() { - VariableReflection* getVariable() - { - return (VariableReflection*) spReflectionVariableLayout_GetVariable((SlangReflectionVariableLayout*) this); - } + return spReflectionVariableLayout_getStage((SlangReflectionVariableLayout*)this); + } - char const* getName() - { - return getVariable()->getName(); - } + VariableLayoutReflection* getPendingDataLayout() + { + return (VariableLayoutReflection*)spReflectionVariableLayout_getPendingDataLayout( + (SlangReflectionVariableLayout*)this); + } +}; - Modifier* findModifier(Modifier::ID id) - { - return getVariable()->findModifier(id); - } +struct FunctionReflection +{ + char const* getName() { return spReflectionFunction_GetName((SlangReflectionFunction*)this); } - TypeLayoutReflection* getTypeLayout() - { - return (TypeLayoutReflection*) spReflectionVariableLayout_GetTypeLayout((SlangReflectionVariableLayout*) this); - } + TypeReflection* getReturnType() + { + return (TypeReflection*)spReflectionFunction_GetResultType((SlangReflectionFunction*)this); + } - ParameterCategory getCategory() - { - return getTypeLayout()->getParameterCategory(); - } + unsigned int getParameterCount() + { + return spReflectionFunction_GetParameterCount((SlangReflectionFunction*)this); + } - unsigned int getCategoryCount() - { - return getTypeLayout()->getCategoryCount(); - } + VariableReflection* getParameterByIndex(unsigned int index) + { + return (VariableReflection*)spReflectionFunction_GetParameter( + (SlangReflectionFunction*)this, + index); + } - ParameterCategory getCategoryByIndex(unsigned int index) - { - return getTypeLayout()->getCategoryByIndex(index); - } + unsigned int getUserAttributeCount() + { + return spReflectionFunction_GetUserAttributeCount((SlangReflectionFunction*)this); + } + UserAttribute* getUserAttributeByIndex(unsigned int index) + { + return (UserAttribute*)spReflectionFunction_GetUserAttribute( + (SlangReflectionFunction*)this, + index); + } + UserAttribute* findUserAttributeByName(SlangSession* globalSession, char const* name) + { + return (UserAttribute*)spReflectionFunction_FindUserAttributeByName( + (SlangReflectionFunction*)this, + globalSession, + name); + } + Modifier* findModifier(Modifier::ID id) + { + return (Modifier*)spReflectionFunction_FindModifier( + (SlangReflectionFunction*)this, + (SlangModifierID)id); + } - size_t getOffset(SlangParameterCategory category = SLANG_PARAMETER_CATEGORY_UNIFORM) - { - return spReflectionVariableLayout_GetOffset((SlangReflectionVariableLayout*) this, category); - } + GenericReflection* getGenericContainer() + { + return (GenericReflection*)spReflectionFunction_GetGenericContainer( + (SlangReflectionFunction*)this); + } - TypeReflection* getType() - { - return getVariable()->getType(); - } + FunctionReflection* applySpecializations(GenericReflection* generic) + { + return (FunctionReflection*)spReflectionFunction_applySpecializations( + (SlangReflectionFunction*)this, + (SlangReflectionGeneric*)generic); + } - unsigned getBindingIndex() - { - return spReflectionParameter_GetBindingIndex((SlangReflectionVariableLayout*) this); - } + FunctionReflection* specializeWithArgTypes(unsigned int argCount, TypeReflection* const* types) + { + return (FunctionReflection*)spReflectionFunction_specializeWithArgTypes( + (SlangReflectionFunction*)this, + argCount, + (SlangReflectionType* const*)types); + } - unsigned getBindingSpace() - { - return spReflectionParameter_GetBindingSpace((SlangReflectionVariableLayout*) this); - } + bool isOverloaded() + { + return spReflectionFunction_isOverloaded((SlangReflectionFunction*)this); + } - size_t getBindingSpace(SlangParameterCategory category) - { - return spReflectionVariableLayout_GetSpace((SlangReflectionVariableLayout*) this, category); - } + unsigned int getOverloadCount() + { + return spReflectionFunction_getOverloadCount((SlangReflectionFunction*)this); + } - char const* getSemanticName() - { - return spReflectionVariableLayout_GetSemanticName((SlangReflectionVariableLayout*) this); - } + FunctionReflection* getOverload(unsigned int index) + { + return (FunctionReflection*)spReflectionFunction_getOverload( + (SlangReflectionFunction*)this, + index); + } +}; - size_t getSemanticIndex() - { - return spReflectionVariableLayout_GetSemanticIndex((SlangReflectionVariableLayout*) this); - } +struct GenericReflection +{ - SlangStage getStage() - { - return spReflectionVariableLayout_getStage((SlangReflectionVariableLayout*) this); - } + DeclReflection* asDecl() + { + return (DeclReflection*)spReflectionGeneric_asDecl((SlangReflectionGeneric*)this); + } - VariableLayoutReflection* getPendingDataLayout() - { - return (VariableLayoutReflection*) spReflectionVariableLayout_getPendingDataLayout((SlangReflectionVariableLayout*) this); - } - }; + char const* getName() { return spReflectionGeneric_GetName((SlangReflectionGeneric*)this); } - struct FunctionReflection + unsigned int getTypeParameterCount() { - char const* getName() - { - return spReflectionFunction_GetName((SlangReflectionFunction*)this); - } + return spReflectionGeneric_GetTypeParameterCount((SlangReflectionGeneric*)this); + } - TypeReflection* getReturnType() - { - return (TypeReflection*)spReflectionFunction_GetResultType((SlangReflectionFunction*)this); - } + VariableReflection* getTypeParameter(unsigned index) + { + return (VariableReflection*)spReflectionGeneric_GetTypeParameter( + (SlangReflectionGeneric*)this, + index); + } - unsigned int getParameterCount() - { - return spReflectionFunction_GetParameterCount((SlangReflectionFunction*)this); - } + unsigned int getValueParameterCount() + { + return spReflectionGeneric_GetValueParameterCount((SlangReflectionGeneric*)this); + } - VariableReflection* getParameterByIndex(unsigned int index) - { - return (VariableReflection*)spReflectionFunction_GetParameter((SlangReflectionFunction*)this, index); - } + VariableReflection* getValueParameter(unsigned index) + { + return (VariableReflection*)spReflectionGeneric_GetValueParameter( + (SlangReflectionGeneric*)this, + index); + } - unsigned int getUserAttributeCount() - { - return spReflectionFunction_GetUserAttributeCount((SlangReflectionFunction*)this); - } - UserAttribute* getUserAttributeByIndex(unsigned int index) - { - return (UserAttribute*)spReflectionFunction_GetUserAttribute((SlangReflectionFunction*)this, index); - } - UserAttribute* findUserAttributeByName(SlangSession* globalSession, char const* name) - { - return (UserAttribute*)spReflectionFunction_FindUserAttributeByName((SlangReflectionFunction*)this, globalSession, name); - } + unsigned int getTypeParameterConstraintCount(VariableReflection* typeParam) + { + return spReflectionGeneric_GetTypeParameterConstraintCount( + (SlangReflectionGeneric*)this, + (SlangReflectionVariable*)typeParam); + } - Modifier* findModifier(Modifier::ID id) - { - return (Modifier*)spReflectionFunction_FindModifier((SlangReflectionFunction*)this, (SlangModifierID)id); - } + TypeReflection* getTypeParameterConstraintType(VariableReflection* typeParam, unsigned index) + { + return (TypeReflection*)spReflectionGeneric_GetTypeParameterConstraintType( + (SlangReflectionGeneric*)this, + (SlangReflectionVariable*)typeParam, + index); + } - GenericReflection* getGenericContainer() - { - return (GenericReflection*)spReflectionFunction_GetGenericContainer((SlangReflectionFunction*)this); - } + DeclReflection* getInnerDecl() + { + return (DeclReflection*)spReflectionGeneric_GetInnerDecl((SlangReflectionGeneric*)this); + } - FunctionReflection* applySpecializations(GenericReflection* generic) - { - return (FunctionReflection*)spReflectionFunction_applySpecializations((SlangReflectionFunction*)this, (SlangReflectionGeneric*)generic); - } + SlangDeclKind getInnerKind() + { + return spReflectionGeneric_GetInnerKind((SlangReflectionGeneric*)this); + } - FunctionReflection* specializeWithArgTypes(unsigned int argCount, TypeReflection* const* types) - { - return (FunctionReflection*)spReflectionFunction_specializeWithArgTypes((SlangReflectionFunction*)this, argCount, (SlangReflectionType* const*)types); - } + GenericReflection* getOuterGenericContainer() + { + return (GenericReflection*)spReflectionGeneric_GetOuterGenericContainer( + (SlangReflectionGeneric*)this); + } - bool isOverloaded() - { - return spReflectionFunction_isOverloaded((SlangReflectionFunction*)this); - } + TypeReflection* getConcreteType(VariableReflection* typeParam) + { + return (TypeReflection*)spReflectionGeneric_GetConcreteType( + (SlangReflectionGeneric*)this, + (SlangReflectionVariable*)typeParam); + } - unsigned int getOverloadCount() - { - return spReflectionFunction_getOverloadCount((SlangReflectionFunction*)this); - } + int64_t getConcreteIntVal(VariableReflection* valueParam) + { + return spReflectionGeneric_GetConcreteIntVal( + (SlangReflectionGeneric*)this, + (SlangReflectionVariable*)valueParam); + } - FunctionReflection* getOverload(unsigned int index) - { - return (FunctionReflection*)spReflectionFunction_getOverload((SlangReflectionFunction*)this, index); - } - }; + GenericReflection* applySpecializations(GenericReflection* generic) + { + return (GenericReflection*)spReflectionGeneric_applySpecializations( + (SlangReflectionGeneric*)this, + (SlangReflectionGeneric*)generic); + } +}; - struct GenericReflection +struct EntryPointReflection +{ + char const* getName() { + return spReflectionEntryPoint_getName((SlangReflectionEntryPoint*)this); + } - DeclReflection* asDecl() - { - return (DeclReflection*)spReflectionGeneric_asDecl((SlangReflectionGeneric*)this); - } + char const* getNameOverride() + { + return spReflectionEntryPoint_getNameOverride((SlangReflectionEntryPoint*)this); + } - char const* getName() - { - return spReflectionGeneric_GetName((SlangReflectionGeneric*)this); - } + unsigned getParameterCount() + { + return spReflectionEntryPoint_getParameterCount((SlangReflectionEntryPoint*)this); + } - unsigned int getTypeParameterCount() - { - return spReflectionGeneric_GetTypeParameterCount((SlangReflectionGeneric*)this); - } + FunctionReflection* getFunction() + { + return (FunctionReflection*)spReflectionEntryPoint_getFunction( + (SlangReflectionEntryPoint*)this); + } - VariableReflection* getTypeParameter(unsigned index) - { - return (VariableReflection*)spReflectionGeneric_GetTypeParameter((SlangReflectionGeneric*)this, index); - } + VariableLayoutReflection* getParameterByIndex(unsigned index) + { + return (VariableLayoutReflection*)spReflectionEntryPoint_getParameterByIndex( + (SlangReflectionEntryPoint*)this, + index); + } - unsigned int getValueParameterCount() - { - return spReflectionGeneric_GetValueParameterCount((SlangReflectionGeneric*)this); - } + SlangStage getStage() + { + return spReflectionEntryPoint_getStage((SlangReflectionEntryPoint*)this); + } - VariableReflection* getValueParameter(unsigned index) - { - return (VariableReflection*)spReflectionGeneric_GetValueParameter((SlangReflectionGeneric*)this, index); - } + void getComputeThreadGroupSize(SlangUInt axisCount, SlangUInt* outSizeAlongAxis) + { + return spReflectionEntryPoint_getComputeThreadGroupSize( + (SlangReflectionEntryPoint*)this, + axisCount, + outSizeAlongAxis); + } - unsigned int getTypeParameterConstraintCount(VariableReflection* typeParam) - { - return spReflectionGeneric_GetTypeParameterConstraintCount((SlangReflectionGeneric*)this, (SlangReflectionVariable*)typeParam); - } + void getComputeWaveSize(SlangUInt* outWaveSize) + { + return spReflectionEntryPoint_getComputeWaveSize( + (SlangReflectionEntryPoint*)this, + outWaveSize); + } - TypeReflection* getTypeParameterConstraintType(VariableReflection* typeParam, unsigned index) - { - return (TypeReflection*)spReflectionGeneric_GetTypeParameterConstraintType((SlangReflectionGeneric*)this, (SlangReflectionVariable*)typeParam, index); - } + bool usesAnySampleRateInput() + { + return 0 != spReflectionEntryPoint_usesAnySampleRateInput((SlangReflectionEntryPoint*)this); + } - DeclReflection* getInnerDecl() - { - return (DeclReflection*)spReflectionGeneric_GetInnerDecl((SlangReflectionGeneric*)this); - } + VariableLayoutReflection* getVarLayout() + { + return (VariableLayoutReflection*)spReflectionEntryPoint_getVarLayout( + (SlangReflectionEntryPoint*)this); + } - SlangDeclKind getInnerKind() - { - return spReflectionGeneric_GetInnerKind((SlangReflectionGeneric*)this); - } + TypeLayoutReflection* getTypeLayout() { return getVarLayout()->getTypeLayout(); } - GenericReflection* getOuterGenericContainer() - { - return (GenericReflection*)spReflectionGeneric_GetOuterGenericContainer((SlangReflectionGeneric*)this); - } + VariableLayoutReflection* getResultVarLayout() + { + return (VariableLayoutReflection*)spReflectionEntryPoint_getResultVarLayout( + (SlangReflectionEntryPoint*)this); + } - TypeReflection* getConcreteType(VariableReflection* typeParam) - { - return (TypeReflection*)spReflectionGeneric_GetConcreteType((SlangReflectionGeneric*)this, (SlangReflectionVariable*)typeParam); - } + bool hasDefaultConstantBuffer() + { + return spReflectionEntryPoint_hasDefaultConstantBuffer((SlangReflectionEntryPoint*)this) != + 0; + } +}; - int64_t getConcreteIntVal(VariableReflection* valueParam) - { - return spReflectionGeneric_GetConcreteIntVal((SlangReflectionGeneric*)this, (SlangReflectionVariable*)valueParam); - } +typedef EntryPointReflection EntryPointLayout; - GenericReflection* applySpecializations(GenericReflection* generic) - { - return (GenericReflection*)spReflectionGeneric_applySpecializations((SlangReflectionGeneric*)this, (SlangReflectionGeneric*)generic); - } - }; +struct TypeParameterReflection +{ + char const* getName() + { + return spReflectionTypeParameter_GetName((SlangReflectionTypeParameter*)this); + } + unsigned getIndex() + { + return spReflectionTypeParameter_GetIndex((SlangReflectionTypeParameter*)this); + } + unsigned getConstraintCount() + { + return spReflectionTypeParameter_GetConstraintCount((SlangReflectionTypeParameter*)this); + } + TypeReflection* getConstraintByIndex(int index) + { + return (TypeReflection*)spReflectionTypeParameter_GetConstraintByIndex( + (SlangReflectionTypeParameter*)this, + index); + } +}; + +enum class LayoutRules : SlangLayoutRulesIntegral +{ + Default = SLANG_LAYOUT_RULES_DEFAULT, + MetalArgumentBufferTier2 = SLANG_LAYOUT_RULES_METAL_ARGUMENT_BUFFER_TIER_2, +}; + +typedef struct ShaderReflection ProgramLayout; +typedef enum SlangReflectionGenericArgType GenericArgType; + +struct ShaderReflection +{ + unsigned getParameterCount() { return spReflection_GetParameterCount((SlangReflection*)this); } - struct EntryPointReflection + unsigned getTypeParameterCount() { - char const* getName() - { - return spReflectionEntryPoint_getName((SlangReflectionEntryPoint*) this); - } + return spReflection_GetTypeParameterCount((SlangReflection*)this); + } - char const* getNameOverride() - { - return spReflectionEntryPoint_getNameOverride((SlangReflectionEntryPoint*)this); - } + slang::ISession* getSession() { return spReflection_GetSession((SlangReflection*)this); } - unsigned getParameterCount() - { - return spReflectionEntryPoint_getParameterCount((SlangReflectionEntryPoint*) this); - } + TypeParameterReflection* getTypeParameterByIndex(unsigned index) + { + return (TypeParameterReflection*)spReflection_GetTypeParameterByIndex( + (SlangReflection*)this, + index); + } - FunctionReflection* getFunction() - { - return (FunctionReflection*)spReflectionEntryPoint_getFunction((SlangReflectionEntryPoint*) this); - } + TypeParameterReflection* findTypeParameter(char const* name) + { + return ( + TypeParameterReflection*)spReflection_FindTypeParameter((SlangReflection*)this, name); + } - VariableLayoutReflection* getParameterByIndex(unsigned index) - { - return (VariableLayoutReflection*) spReflectionEntryPoint_getParameterByIndex((SlangReflectionEntryPoint*) this, index); - } + VariableLayoutReflection* getParameterByIndex(unsigned index) + { + return (VariableLayoutReflection*)spReflection_GetParameterByIndex( + (SlangReflection*)this, + index); + } - SlangStage getStage() - { - return spReflectionEntryPoint_getStage((SlangReflectionEntryPoint*) this); - } + static ProgramLayout* get(SlangCompileRequest* request) + { + return (ProgramLayout*)spGetReflection(request); + } - void getComputeThreadGroupSize( - SlangUInt axisCount, - SlangUInt* outSizeAlongAxis) - { - return spReflectionEntryPoint_getComputeThreadGroupSize((SlangReflectionEntryPoint*) this, axisCount, outSizeAlongAxis); - } + SlangUInt getEntryPointCount() + { + return spReflection_getEntryPointCount((SlangReflection*)this); + } - void getComputeWaveSize( - SlangUInt* outWaveSize) - { - return spReflectionEntryPoint_getComputeWaveSize((SlangReflectionEntryPoint*)this, outWaveSize); - } + EntryPointReflection* getEntryPointByIndex(SlangUInt index) + { + return ( + EntryPointReflection*)spReflection_getEntryPointByIndex((SlangReflection*)this, index); + } + + SlangUInt getGlobalConstantBufferBinding() + { + return spReflection_getGlobalConstantBufferBinding((SlangReflection*)this); + } + + size_t getGlobalConstantBufferSize() + { + return spReflection_getGlobalConstantBufferSize((SlangReflection*)this); + } + + TypeReflection* findTypeByName(const char* name) + { + return (TypeReflection*)spReflection_FindTypeByName((SlangReflection*)this, name); + } + + FunctionReflection* findFunctionByName(const char* name) + { + return (FunctionReflection*)spReflection_FindFunctionByName((SlangReflection*)this, name); + } + + FunctionReflection* findFunctionByNameInType(TypeReflection* type, const char* name) + { + return (FunctionReflection*)spReflection_FindFunctionByNameInType( + (SlangReflection*)this, + (SlangReflectionType*)type, + name); + } + + VariableReflection* findVarByNameInType(TypeReflection* type, const char* name) + { + return (VariableReflection*)spReflection_FindVarByNameInType( + (SlangReflection*)this, + (SlangReflectionType*)type, + name); + } + + TypeLayoutReflection* getTypeLayout( + TypeReflection* type, + LayoutRules rules = LayoutRules::Default) + { + return (TypeLayoutReflection*)spReflection_GetTypeLayout( + (SlangReflection*)this, + (SlangReflectionType*)type, + SlangLayoutRules(rules)); + } + + EntryPointReflection* findEntryPointByName(const char* name) + { + return ( + EntryPointReflection*)spReflection_findEntryPointByName((SlangReflection*)this, name); + } + + TypeReflection* specializeType( + TypeReflection* type, + SlangInt specializationArgCount, + TypeReflection* const* specializationArgs, + ISlangBlob** outDiagnostics) + { + return (TypeReflection*)spReflection_specializeType( + (SlangReflection*)this, + (SlangReflectionType*)type, + specializationArgCount, + (SlangReflectionType* const*)specializationArgs, + outDiagnostics); + } + + GenericReflection* specializeGeneric( + GenericReflection* generic, + SlangInt specializationArgCount, + GenericArgType const* specializationArgTypes, + GenericArgReflection const* specializationArgVals, + ISlangBlob** outDiagnostics) + { + return (GenericReflection*)spReflection_specializeGeneric( + (SlangReflection*)this, + (SlangReflectionGeneric*)generic, + specializationArgCount, + (SlangReflectionGenericArgType const*)specializationArgTypes, + (SlangReflectionGenericArg const*)specializationArgVals, + outDiagnostics); + } + + bool isSubType(TypeReflection* subType, TypeReflection* superType) + { + return spReflection_isSubType( + (SlangReflection*)this, + (SlangReflectionType*)subType, + (SlangReflectionType*)superType); + } + + SlangUInt getHashedStringCount() const + { + return spReflection_getHashedStringCount((SlangReflection*)this); + } + + const char* getHashedString(SlangUInt index, size_t* outCount) const + { + return spReflection_getHashedString((SlangReflection*)this, index, outCount); + } + + TypeLayoutReflection* getGlobalParamsTypeLayout() + { + return (TypeLayoutReflection*)spReflection_getGlobalParamsTypeLayout( + (SlangReflection*)this); + } + + VariableLayoutReflection* getGlobalParamsVarLayout() + { + return (VariableLayoutReflection*)spReflection_getGlobalParamsVarLayout( + (SlangReflection*)this); + } +}; + + +struct DeclReflection +{ + enum class Kind + { + Unsupported = SLANG_DECL_KIND_UNSUPPORTED_FOR_REFLECTION, + Struct = SLANG_DECL_KIND_STRUCT, + Func = SLANG_DECL_KIND_FUNC, + Module = SLANG_DECL_KIND_MODULE, + Generic = SLANG_DECL_KIND_GENERIC, + Variable = SLANG_DECL_KIND_VARIABLE, + Namespace = SLANG_DECL_KIND_NAMESPACE, + }; + + char const* getName() { return spReflectionDecl_getName((SlangReflectionDecl*)this); } + + Kind getKind() { return (Kind)spReflectionDecl_getKind((SlangReflectionDecl*)this); } + + unsigned int getChildrenCount() + { + return spReflectionDecl_getChildrenCount((SlangReflectionDecl*)this); + } + + DeclReflection* getChild(unsigned int index) + { + return (DeclReflection*)spReflectionDecl_getChild((SlangReflectionDecl*)this, index); + } + + TypeReflection* getType() + { + return (TypeReflection*)spReflection_getTypeFromDecl((SlangReflectionDecl*)this); + } + + VariableReflection* asVariable() + { + return (VariableReflection*)spReflectionDecl_castToVariable((SlangReflectionDecl*)this); + } - bool usesAnySampleRateInput() - { - return 0 != spReflectionEntryPoint_usesAnySampleRateInput((SlangReflectionEntryPoint*) this); - } + FunctionReflection* asFunction() + { + return (FunctionReflection*)spReflectionDecl_castToFunction((SlangReflectionDecl*)this); + } - VariableLayoutReflection* getVarLayout() - { - return (VariableLayoutReflection*) spReflectionEntryPoint_getVarLayout((SlangReflectionEntryPoint*) this); - } + GenericReflection* asGeneric() + { + return (GenericReflection*)spReflectionDecl_castToGeneric((SlangReflectionDecl*)this); + } - TypeLayoutReflection* getTypeLayout() - { - return getVarLayout()->getTypeLayout(); - } + DeclReflection* getParent() + { + return (DeclReflection*)spReflectionDecl_getParent((SlangReflectionDecl*)this); + } - VariableLayoutReflection* getResultVarLayout() - { - return (VariableLayoutReflection*) spReflectionEntryPoint_getResultVarLayout((SlangReflectionEntryPoint*) this); - } + template + struct FilteredList + { + unsigned int count; + DeclReflection* parent; - bool hasDefaultConstantBuffer() + struct FilteredIterator { - return spReflectionEntryPoint_hasDefaultConstantBuffer((SlangReflectionEntryPoint*) this) != 0; - } - }; + DeclReflection* parent; + unsigned int count; + unsigned int index; - typedef EntryPointReflection EntryPointLayout; + DeclReflection* operator*() { return parent->getChild(index); } + void operator++() + { + index++; + while (index < count && !(parent->getChild(index)->getKind() == K)) + { + index++; + } + } + bool operator!=(FilteredIterator const& other) { return index != other.index; } + }; - struct TypeParameterReflection - { - char const* getName() - { - return spReflectionTypeParameter_GetName((SlangReflectionTypeParameter*) this); - } - unsigned getIndex() - { - return spReflectionTypeParameter_GetIndex((SlangReflectionTypeParameter*) this); - } - unsigned getConstraintCount() + // begin/end for range-based for that checks the kind + FilteredIterator begin() { - return spReflectionTypeParameter_GetConstraintCount((SlangReflectionTypeParameter*) this); - } - TypeReflection* getConstraintByIndex(int index) - { - return (TypeReflection*)spReflectionTypeParameter_GetConstraintByIndex((SlangReflectionTypeParameter*) this, index); + // Find the first child of the right kind + unsigned int index = 0; + while (index < count && !(parent->getChild(index)->getKind() == K)) + { + index++; + } + return FilteredIterator{parent, count, index}; } - }; - enum class LayoutRules : SlangLayoutRulesIntegral - { - Default = SLANG_LAYOUT_RULES_DEFAULT, - MetalArgumentBufferTier2 = SLANG_LAYOUT_RULES_METAL_ARGUMENT_BUFFER_TIER_2, + FilteredIterator end() { return FilteredIterator{parent, count, count}; } }; - typedef struct ShaderReflection ProgramLayout; - typedef enum SlangReflectionGenericArgType GenericArgType; - - struct ShaderReflection + template + FilteredList getChildrenOfKind() { - unsigned getParameterCount() - { - return spReflection_GetParameterCount((SlangReflection*) this); - } + return FilteredList{getChildrenCount(), (DeclReflection*)this}; + } - unsigned getTypeParameterCount() - { - return spReflection_GetTypeParameterCount((SlangReflection*) this); - } + struct IteratedList + { + unsigned int count; + DeclReflection* parent; - slang::ISession* getSession() + struct Iterator { - return spReflection_GetSession((SlangReflection*)this); - } + DeclReflection* parent; + unsigned int count; + unsigned int index; - TypeParameterReflection* getTypeParameterByIndex(unsigned index) - { - return (TypeParameterReflection*)spReflection_GetTypeParameterByIndex((SlangReflection*) this, index); - } + DeclReflection* operator*() { return parent->getChild(index); } + void operator++() { index++; } + bool operator!=(Iterator const& other) { return index != other.index; } + }; - TypeParameterReflection* findTypeParameter(char const* name) - { - return (TypeParameterReflection*)spReflection_FindTypeParameter((SlangReflection*)this, name); - } + // begin/end for range-based for that checks the kind + IteratedList::Iterator begin() { return IteratedList::Iterator{parent, count, 0}; } + IteratedList::Iterator end() { return IteratedList::Iterator{parent, count, count}; } + }; - VariableLayoutReflection* getParameterByIndex(unsigned index) - { - return (VariableLayoutReflection*) spReflection_GetParameterByIndex((SlangReflection*) this, index); - } + IteratedList getChildren() { return IteratedList{getChildrenCount(), (DeclReflection*)this}; } +}; - static ProgramLayout* get(SlangCompileRequest* request) - { - return (ProgramLayout*) spGetReflection(request); - } +typedef uint32_t CompileCoreModuleFlags; +struct CompileCoreModuleFlag +{ + enum Enum : CompileCoreModuleFlags + { + WriteDocumentation = 0x1, + }; +}; - SlangUInt getEntryPointCount() - { - return spReflection_getEntryPointCount((SlangReflection*) this); - } +typedef ISlangBlob IBlob; - EntryPointReflection* getEntryPointByIndex(SlangUInt index) - { - return (EntryPointReflection*) spReflection_getEntryPointByIndex((SlangReflection*) this, index); - } +struct IComponentType; +struct ITypeConformance; +struct IGlobalSession; +struct IModule; - SlangUInt getGlobalConstantBufferBinding() - { - return spReflection_getGlobalConstantBufferBinding((SlangReflection*)this); - } +struct SessionDesc; +struct SpecializationArg; +struct TargetDesc; - size_t getGlobalConstantBufferSize() - { - return spReflection_getGlobalConstantBufferSize((SlangReflection*)this); - } +/** A global session for interaction with the Slang library. - TypeReflection* findTypeByName(const char* name) - { - return (TypeReflection*)spReflection_FindTypeByName( - (SlangReflection*) this, - name); - } +An application may create and re-use a single global session across +multiple sessions, in order to amortize startups costs (in current +Slang this is mostly the cost of loading the Slang standard library). - FunctionReflection* findFunctionByName(const char* name) - { - return (FunctionReflection*)spReflection_FindFunctionByName( - (SlangReflection*) this, - name); - } +The global session is currently *not* thread-safe and objects created from +a single global session should only be used from a single thread at +a time. +*/ +struct IGlobalSession : public ISlangUnknown +{ + SLANG_COM_INTERFACE(0xc140b5fd, 0xc78, 0x452e, {0xba, 0x7c, 0x1a, 0x1e, 0x70, 0xc7, 0xf7, 0x1c}) - FunctionReflection* findFunctionByNameInType(TypeReflection* type, const char* name) - { - return (FunctionReflection*)spReflection_FindFunctionByNameInType( - (SlangReflection*) this, - (SlangReflectionType*) type, - name); - } + /** Create a new session for loading and compiling code. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + createSession(SessionDesc const& desc, ISession** outSession) = 0; - VariableReflection* findVarByNameInType(TypeReflection* type, const char* name) - { - return (VariableReflection*)spReflection_FindVarByNameInType( - (SlangReflection*) this, - (SlangReflectionType*) type, - name); - } + /** Look up the internal ID of a profile by its `name`. - TypeLayoutReflection* getTypeLayout( - TypeReflection* type, - LayoutRules rules = LayoutRules::Default) - { - return (TypeLayoutReflection*)spReflection_GetTypeLayout( - (SlangReflection*) this, - (SlangReflectionType*)type, - SlangLayoutRules(rules)); - } + Profile IDs are *not* guaranteed to be stable across versions + of the Slang library, so clients are expected to look up + profiles by name at runtime. + */ + virtual SLANG_NO_THROW SlangProfileID SLANG_MCALL findProfile(char const* name) = 0; - EntryPointReflection* findEntryPointByName(const char* name) - { - return (EntryPointReflection*)spReflection_findEntryPointByName( - (SlangReflection*) this, - name); - } + /** Set the path that downstream compilers (aka back end compilers) will + be looked from. + @param passThrough Identifies the downstream compiler + @param path The path to find the downstream compiler (shared library/dll/executable) - TypeReflection* specializeType( - TypeReflection* type, - SlangInt specializationArgCount, - TypeReflection* const* specializationArgs, - ISlangBlob** outDiagnostics) - { - return (TypeReflection*) spReflection_specializeType( - (SlangReflection*) this, - (SlangReflectionType*) type, - specializationArgCount, - (SlangReflectionType* const*) specializationArgs, - outDiagnostics); - } + For back ends that are dlls/shared libraries, it will mean the path will + be prefixed with the path when calls are made out to ISlangSharedLibraryLoader. + For executables - it will look for executables along the path */ + virtual SLANG_NO_THROW void SLANG_MCALL + setDownstreamCompilerPath(SlangPassThrough passThrough, char const* path) = 0; - GenericReflection* specializeGeneric( - GenericReflection* generic, - SlangInt specializationArgCount, - GenericArgType const* specializationArgTypes, - GenericArgReflection const* specializationArgVals, - ISlangBlob** outDiagnostics) - { - return (GenericReflection*) spReflection_specializeGeneric( - (SlangReflection*) this, - (SlangReflectionGeneric*) generic, - specializationArgCount, - (SlangReflectionGenericArgType const*) specializationArgTypes, - (SlangReflectionGenericArg const*) specializationArgVals, - outDiagnostics); - } + /** DEPRECATED: Use setLanguagePrelude - bool isSubType( - TypeReflection* subType, - TypeReflection* superType) - { - return spReflection_isSubType( - (SlangReflection*) this, - (SlangReflectionType*) subType, - (SlangReflectionType*) superType); - } + Set the 'prelude' for generated code for a 'downstream compiler'. + @param passThrough The downstream compiler for generated code that will have the prelude applied + to it. + @param preludeText The text added pre-pended verbatim before the generated source - SlangUInt getHashedStringCount() const { return spReflection_getHashedStringCount((SlangReflection*)this); } + That for pass-through usage, prelude is not pre-pended, preludes are for code generation only. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + setDownstreamCompilerPrelude(SlangPassThrough passThrough, const char* preludeText) = 0; - const char* getHashedString(SlangUInt index, size_t* outCount) const - { - return spReflection_getHashedString((SlangReflection*)this, index, outCount); - } + /** DEPRECATED: Use getLanguagePrelude - TypeLayoutReflection* getGlobalParamsTypeLayout() - { - return (TypeLayoutReflection*) spReflection_getGlobalParamsTypeLayout((SlangReflection*) this); - } + Get the 'prelude' for generated code for a 'downstream compiler'. + @param passThrough The downstream compiler for generated code that will have the prelude applied + to it. + @param outPrelude On exit holds a blob that holds the string of the prelude. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + getDownstreamCompilerPrelude(SlangPassThrough passThrough, ISlangBlob** outPrelude) = 0; - VariableLayoutReflection* getGlobalParamsVarLayout() - { - return (VariableLayoutReflection*) spReflection_getGlobalParamsVarLayout((SlangReflection*) this); - } - }; + /** Get the build version 'tag' string. The string is the same as produced via `git describe + --tags` for the project. If Slang is built separately from the automated build scripts the + contents will by default be 'unknown'. Any string can be set by changing the contents of + 'slang-tag-version.h' file and recompiling the project. - - struct DeclReflection - { - enum class Kind - { - Unsupported = SLANG_DECL_KIND_UNSUPPORTED_FOR_REFLECTION, - Struct = SLANG_DECL_KIND_STRUCT, - Func = SLANG_DECL_KIND_FUNC, - Module = SLANG_DECL_KIND_MODULE, - Generic = SLANG_DECL_KIND_GENERIC, - Variable = SLANG_DECL_KIND_VARIABLE, - Namespace = SLANG_DECL_KIND_NAMESPACE, - }; + This method will return exactly the same result as the free function spGetBuildTagString. - char const* getName() - { - return spReflectionDecl_getName((SlangReflectionDecl*) this); - } + @return The build tag string + */ + virtual SLANG_NO_THROW const char* SLANG_MCALL getBuildTagString() = 0; - Kind getKind() - { - return (Kind)spReflectionDecl_getKind((SlangReflectionDecl*)this); - } + /* For a given source language set the default compiler. + If a default cannot be chosen (for example the target cannot be achieved by the default), + the default will not be used. - unsigned int getChildrenCount() - { - return spReflectionDecl_getChildrenCount((SlangReflectionDecl*)this); - } + @param sourceLanguage the source language + @param defaultCompiler the default compiler for that language + @return + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL setDefaultDownstreamCompiler( + SlangSourceLanguage sourceLanguage, + SlangPassThrough defaultCompiler) = 0; - DeclReflection* getChild(unsigned int index) - { - return (DeclReflection*)spReflectionDecl_getChild((SlangReflectionDecl*)this, index); - } + /* For a source type get the default compiler - TypeReflection* getType() - { - return (TypeReflection*)spReflection_getTypeFromDecl((SlangReflectionDecl*)this); - } + @param sourceLanguage the source language + @return The downstream compiler for that source language */ + virtual SlangPassThrough SLANG_MCALL + getDefaultDownstreamCompiler(SlangSourceLanguage sourceLanguage) = 0; - VariableReflection* asVariable() - { - return (VariableReflection*)spReflectionDecl_castToVariable((SlangReflectionDecl*)this); - } + /* Set the 'prelude' placed before generated code for a specific language type. - FunctionReflection* asFunction() - { - return (FunctionReflection*)spReflectionDecl_castToFunction((SlangReflectionDecl*)this); - } + @param sourceLanguage The language the prelude should be inserted on. + @param preludeText The text added pre-pended verbatim before the generated source - GenericReflection* asGeneric() - { - return (GenericReflection*)spReflectionDecl_castToGeneric((SlangReflectionDecl*)this); - } + Note! That for pass-through usage, prelude is not pre-pended, preludes are for code generation + only. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + setLanguagePrelude(SlangSourceLanguage sourceLanguage, const char* preludeText) = 0; - DeclReflection* getParent() - { - return (DeclReflection*)spReflectionDecl_getParent((SlangReflectionDecl*)this); - } + /** Get the 'prelude' associated with a specific source language. + @param sourceLanguage The language the prelude should be inserted on. + @param outPrelude On exit holds a blob that holds the string of the prelude. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + getLanguagePrelude(SlangSourceLanguage sourceLanguage, ISlangBlob** outPrelude) = 0; + + /** Create a compile request. + */ + [[deprecated]] virtual SLANG_NO_THROW SlangResult SLANG_MCALL + createCompileRequest(slang::ICompileRequest** outCompileRequest) = 0; + + /** Add new builtin declarations to be used in subsequent compiles. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + addBuiltins(char const* sourcePath, char const* sourceString) = 0; + + /** Set the session shared library loader. If this changes the loader, it may cause shared + libraries to be unloaded + @param loader The loader to set. Setting nullptr sets the default loader. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + setSharedLibraryLoader(ISlangSharedLibraryLoader* loader) = 0; - template - struct FilteredList - { - unsigned int count; - DeclReflection* parent; + /** Gets the currently set shared library loader + @return Gets the currently set loader. If returns nullptr, it's the default loader + */ + virtual SLANG_NO_THROW ISlangSharedLibraryLoader* SLANG_MCALL getSharedLibraryLoader() = 0; + + /** Returns SLANG_OK if a the compilation target is supported for this session + + @param target The compilation target to test + @return SLANG_OK if the target is available + SLANG_E_NOT_IMPLEMENTED if not implemented in this build + SLANG_E_NOT_FOUND if other resources (such as shared libraries) required to make target work + could not be found SLANG_FAIL other kinds of failures */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + checkCompileTargetSupport(SlangCompileTarget target) = 0; + + /** Returns SLANG_OK if a the pass through support is supported for this session + @param session Session + @param target The compilation target to test + @return SLANG_OK if the target is available + SLANG_E_NOT_IMPLEMENTED if not implemented in this build + SLANG_E_NOT_FOUND if other resources (such as shared libraries) required to make target work + could not be found SLANG_FAIL other kinds of failures */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + checkPassThroughSupport(SlangPassThrough passThrough) = 0; + + /** Compile from (embedded source) the core module on the session. + Will return a failure if there is already a core module available + NOTE! API is experimental and not ready for production code + @param flags to control compilation + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compileCoreModule(CompileCoreModuleFlags flags) = 0; - struct FilteredIterator - { - DeclReflection* parent; - unsigned int count; - unsigned int index; + /** Load the core module. Currently loads modules from the file system. + @param coreModule Start address of the serialized core module + @param coreModuleSizeInBytes The size in bytes of the serialized core module - DeclReflection* operator*() { return parent->getChild(index); } - void operator++() - { - index++; - while (index < count && !(parent->getChild(index)->getKind() == K)) - { - index++; - } - } - bool operator!=(FilteredIterator const& other) { return index != other.index; } - }; - - // begin/end for range-based for that checks the kind - FilteredIterator begin() - { - // Find the first child of the right kind - unsigned int index = 0; - while (index < count && !(parent->getChild(index)->getKind() == K)) - { - index++; - } - return FilteredIterator{parent, count, index}; - } + NOTE! API is experimental and not ready for production code + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + loadCoreModule(const void* coreModule, size_t coreModuleSizeInBytes) = 0; - FilteredIterator end() { return FilteredIterator{parent, count, count}; } - }; - - template - FilteredList getChildrenOfKind() - { - return FilteredList{ getChildrenCount(), (DeclReflection*)this }; - } + /** Save the core module to the file system + @param archiveType The type of archive used to hold the core module + @param outBlob The serialized blob containing the core module - struct IteratedList - { - unsigned int count; - DeclReflection* parent; + NOTE! API is experimental and not ready for production code */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + saveCoreModule(SlangArchiveType archiveType, ISlangBlob** outBlob) = 0; - struct Iterator - { - DeclReflection* parent; - unsigned int count; - unsigned int index; - - DeclReflection* operator*() { return parent->getChild(index); } - void operator++() { index++; } - bool operator!=(Iterator const& other) { return index != other.index; } - }; - - // begin/end for range-based for that checks the kind - IteratedList::Iterator begin() { return IteratedList::Iterator{ parent, count, 0 }; } - IteratedList::Iterator end() { return IteratedList::Iterator{ parent, count, count }; } - }; + /** Look up the internal ID of a capability by its `name`. - IteratedList getChildren() - { - return IteratedList{ getChildrenCount(), (DeclReflection*)this }; - } + Capability IDs are *not* guaranteed to be stable across versions + of the Slang library, so clients are expected to look up + capabilities by name at runtime. + */ + virtual SLANG_NO_THROW SlangCapabilityID SLANG_MCALL findCapability(char const* name) = 0; - }; + /** Set the downstream/pass through compiler to be used for a transition from the source type to + the target type + @param source The source 'code gen target' + @param target The target 'code gen target' + @param compiler The compiler/pass through to use for the transition from source to target + */ + virtual SLANG_NO_THROW void SLANG_MCALL setDownstreamCompilerForTransition( + SlangCompileTarget source, + SlangCompileTarget target, + SlangPassThrough compiler) = 0; + + /** Get the downstream/pass through compiler for a transition specified by source and target + @param source The source 'code gen target' + @param target The target 'code gen target' + @return The compiler that is used for the transition. Returns SLANG_PASS_THROUGH_NONE it is not + defined + */ + virtual SLANG_NO_THROW SlangPassThrough SLANG_MCALL + getDownstreamCompilerForTransition(SlangCompileTarget source, SlangCompileTarget target) = 0; + + /** Get the time in seconds spent in the slang and downstream compiler. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + getCompilerElapsedTime(double* outTotalTime, double* outDownstreamTime) = 0; + + /** Specify a spirv.core.grammar.json file to load and use when + * parsing and checking any SPIR-V code + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL setSPIRVCoreGrammar(char const* jsonPath) = 0; + + /** Parse slangc command line options into a SessionDesc that can be used to create a session + * with all the compiler options specified in the command line. + * @param argc The number of command line arguments. + * @param argv An input array of command line arguments to parse. + * @param outSessionDesc A pointer to a SessionDesc struct to receive parsed session desc. + * @param outAuxAllocation Auxillary memory allocated to hold data used in the sesion desc. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL parseCommandLineArguments( + int argc, + const char* const* argv, + SessionDesc* outSessionDesc, + ISlangUnknown** outAuxAllocation) = 0; + + /** Computes a digest that uniquely identifies the session description. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getSessionDescDigest(SessionDesc* sessionDesc, ISlangBlob** outBlob) = 0; +}; - typedef uint32_t CompileCoreModuleFlags; - struct CompileCoreModuleFlag - { - enum Enum : CompileCoreModuleFlags - { - WriteDocumentation = 0x1, - }; - }; + #define SLANG_UUID_IGlobalSession IGlobalSession::getTypeGuid() - typedef ISlangBlob IBlob; +/** Description of a code generation target. + */ +struct TargetDesc +{ + /** The size of this structure, in bytes. + */ + size_t structureSize = sizeof(TargetDesc); - struct IComponentType; - struct ITypeConformance; - struct IGlobalSession; - struct IModule; + /** The target format to generate code for (e.g., SPIR-V, DXIL, etc.) + */ + SlangCompileTarget format = SLANG_TARGET_UNKNOWN; - struct SessionDesc; - struct SpecializationArg; - struct TargetDesc; + /** The compilation profile supported by the target (e.g., "Shader Model 5.1") + */ + SlangProfileID profile = SLANG_PROFILE_UNKNOWN; - /** A global session for interaction with the Slang library. + /** Flags for the code generation target. Currently unused. */ + SlangTargetFlags flags = kDefaultTargetFlags; - An application may create and re-use a single global session across - multiple sessions, in order to amortize startups costs (in current - Slang this is mostly the cost of loading the Slang standard library). + /** Default mode to use for floating-point operations on the target. + */ + SlangFloatingPointMode floatingPointMode = SLANG_FLOATING_POINT_MODE_DEFAULT; - The global session is currently *not* thread-safe and objects created from - a single global session should only be used from a single thread at - a time. - */ - struct IGlobalSession : public ISlangUnknown - { - SLANG_COM_INTERFACE(0xc140b5fd, 0xc78, 0x452e, { 0xba, 0x7c, 0x1a, 0x1e, 0x70, 0xc7, 0xf7, 0x1c }) - - /** Create a new session for loading and compiling code. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createSession( - SessionDesc const& desc, - ISession** outSession) = 0; - - /** Look up the internal ID of a profile by its `name`. - - Profile IDs are *not* guaranteed to be stable across versions - of the Slang library, so clients are expected to look up - profiles by name at runtime. - */ - virtual SLANG_NO_THROW SlangProfileID SLANG_MCALL findProfile( - char const* name) = 0; - - /** Set the path that downstream compilers (aka back end compilers) will - be looked from. - @param passThrough Identifies the downstream compiler - @param path The path to find the downstream compiler (shared library/dll/executable) - - For back ends that are dlls/shared libraries, it will mean the path will - be prefixed with the path when calls are made out to ISlangSharedLibraryLoader. - For executables - it will look for executables along the path */ - virtual SLANG_NO_THROW void SLANG_MCALL setDownstreamCompilerPath( - SlangPassThrough passThrough, - char const* path) = 0; - - /** DEPRECATED: Use setLanguagePrelude - - Set the 'prelude' for generated code for a 'downstream compiler'. - @param passThrough The downstream compiler for generated code that will have the prelude applied to it. - @param preludeText The text added pre-pended verbatim before the generated source - - That for pass-through usage, prelude is not pre-pended, preludes are for code generation only. - */ - virtual SLANG_NO_THROW void SLANG_MCALL setDownstreamCompilerPrelude( - SlangPassThrough passThrough, - const char* preludeText) = 0; - - /** DEPRECATED: Use getLanguagePrelude - - Get the 'prelude' for generated code for a 'downstream compiler'. - @param passThrough The downstream compiler for generated code that will have the prelude applied to it. - @param outPrelude On exit holds a blob that holds the string of the prelude. - */ - virtual SLANG_NO_THROW void SLANG_MCALL getDownstreamCompilerPrelude( - SlangPassThrough passThrough, - ISlangBlob** outPrelude) = 0; - - /** Get the build version 'tag' string. The string is the same as produced via `git describe --tags` - for the project. If Slang is built separately from the automated build scripts - the contents will by default be 'unknown'. Any string can be set by changing the - contents of 'slang-tag-version.h' file and recompiling the project. - - This method will return exactly the same result as the free function spGetBuildTagString. - - @return The build tag string - */ - virtual SLANG_NO_THROW const char* SLANG_MCALL getBuildTagString() = 0; - - /* For a given source language set the default compiler. - If a default cannot be chosen (for example the target cannot be achieved by the default), - the default will not be used. - - @param sourceLanguage the source language - @param defaultCompiler the default compiler for that language - @return - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL setDefaultDownstreamCompiler( - SlangSourceLanguage sourceLanguage, - SlangPassThrough defaultCompiler) = 0; - - /* For a source type get the default compiler - - @param sourceLanguage the source language - @return The downstream compiler for that source language */ - virtual SlangPassThrough SLANG_MCALL getDefaultDownstreamCompiler( - SlangSourceLanguage sourceLanguage) = 0; - - /* Set the 'prelude' placed before generated code for a specific language type. - - @param sourceLanguage The language the prelude should be inserted on. - @param preludeText The text added pre-pended verbatim before the generated source - - Note! That for pass-through usage, prelude is not pre-pended, preludes are for code generation only. - */ - virtual SLANG_NO_THROW void SLANG_MCALL setLanguagePrelude( - SlangSourceLanguage sourceLanguage, - const char* preludeText) = 0; - - /** Get the 'prelude' associated with a specific source language. - @param sourceLanguage The language the prelude should be inserted on. - @param outPrelude On exit holds a blob that holds the string of the prelude. - */ - virtual SLANG_NO_THROW void SLANG_MCALL getLanguagePrelude( - SlangSourceLanguage sourceLanguage, - ISlangBlob** outPrelude) = 0; - - /** Create a compile request. - */ - [[deprecated]] - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createCompileRequest( - slang::ICompileRequest** outCompileRequest) = 0; - - /** Add new builtin declarations to be used in subsequent compiles. - */ - virtual SLANG_NO_THROW void SLANG_MCALL addBuiltins( - char const* sourcePath, - char const* sourceString) = 0; - - /** Set the session shared library loader. If this changes the loader, it may cause shared libraries to be unloaded - @param loader The loader to set. Setting nullptr sets the default loader. - */ - virtual SLANG_NO_THROW void SLANG_MCALL setSharedLibraryLoader( - ISlangSharedLibraryLoader* loader) = 0; - - /** Gets the currently set shared library loader - @return Gets the currently set loader. If returns nullptr, it's the default loader - */ - virtual SLANG_NO_THROW ISlangSharedLibraryLoader* SLANG_MCALL getSharedLibraryLoader() = 0; - - /** Returns SLANG_OK if a the compilation target is supported for this session - - @param target The compilation target to test - @return SLANG_OK if the target is available - SLANG_E_NOT_IMPLEMENTED if not implemented in this build - SLANG_E_NOT_FOUND if other resources (such as shared libraries) required to make target work could not be found - SLANG_FAIL other kinds of failures */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL checkCompileTargetSupport( - SlangCompileTarget target) = 0; - - /** Returns SLANG_OK if a the pass through support is supported for this session - @param session Session - @param target The compilation target to test - @return SLANG_OK if the target is available - SLANG_E_NOT_IMPLEMENTED if not implemented in this build - SLANG_E_NOT_FOUND if other resources (such as shared libraries) required to make target work could not be found - SLANG_FAIL other kinds of failures */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL checkPassThroughSupport( - SlangPassThrough passThrough) = 0; - - /** Compile from (embedded source) the core module on the session. - Will return a failure if there is already a core module available - NOTE! API is experimental and not ready for production code - @param flags to control compilation - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compileCoreModule(CompileCoreModuleFlags flags) = 0; - - /** Load the core module. Currently loads modules from the file system. - @param coreModule Start address of the serialized core module - @param coreModuleSizeInBytes The size in bytes of the serialized core module - - NOTE! API is experimental and not ready for production code - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadCoreModule(const void* coreModule, size_t coreModuleSizeInBytes) = 0; - - /** Save the core module to the file system - @param archiveType The type of archive used to hold the core module - @param outBlob The serialized blob containing the core module - - NOTE! API is experimental and not ready for production code */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL saveCoreModule(SlangArchiveType archiveType, ISlangBlob** outBlob) = 0; - - /** Look up the internal ID of a capability by its `name`. - - Capability IDs are *not* guaranteed to be stable across versions - of the Slang library, so clients are expected to look up - capabilities by name at runtime. - */ - virtual SLANG_NO_THROW SlangCapabilityID SLANG_MCALL findCapability( - char const* name) = 0; - - /** Set the downstream/pass through compiler to be used for a transition from the source type to the target type - @param source The source 'code gen target' - @param target The target 'code gen target' - @param compiler The compiler/pass through to use for the transition from source to target - */ - virtual SLANG_NO_THROW void SLANG_MCALL setDownstreamCompilerForTransition(SlangCompileTarget source, SlangCompileTarget target, SlangPassThrough compiler) = 0; - - /** Get the downstream/pass through compiler for a transition specified by source and target - @param source The source 'code gen target' - @param target The target 'code gen target' - @return The compiler that is used for the transition. Returns SLANG_PASS_THROUGH_NONE it is not defined - */ - virtual SLANG_NO_THROW SlangPassThrough SLANG_MCALL getDownstreamCompilerForTransition(SlangCompileTarget source, SlangCompileTarget target) = 0; - - /** Get the time in seconds spent in the slang and downstream compiler. - */ - virtual SLANG_NO_THROW void SLANG_MCALL getCompilerElapsedTime(double* outTotalTime, double* outDownstreamTime) = 0; - - /** Specify a spirv.core.grammar.json file to load and use when - * parsing and checking any SPIR-V code - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL setSPIRVCoreGrammar( - char const* jsonPath) = 0; - - /** Parse slangc command line options into a SessionDesc that can be used to create a session - * with all the compiler options specified in the command line. - * @param argc The number of command line arguments. - * @param argv An input array of command line arguments to parse. - * @param outSessionDesc A pointer to a SessionDesc struct to receive parsed session desc. - * @param outAuxAllocation Auxillary memory allocated to hold data used in the sesion desc. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL parseCommandLineArguments( - int argc, const char* const* argv, SessionDesc* outSessionDesc, ISlangUnknown** outAuxAllocation) = 0; - - /** Computes a digest that uniquely identifies the session description. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getSessionDescDigest(SessionDesc* sessionDesc, ISlangBlob** outBlob) = 0; - }; + /** The line directive mode for output source code. + */ + SlangLineDirectiveMode lineDirectiveMode = SLANG_LINE_DIRECTIVE_MODE_DEFAULT; - #define SLANG_UUID_IGlobalSession IGlobalSession::getTypeGuid() + /** Whether to force `scalar` layout for glsl shader storage buffers. + */ + bool forceGLSLScalarBufferLayout = false; - /** Description of a code generation target. - */ - struct TargetDesc - { - /** The size of this structure, in bytes. - */ - size_t structureSize = sizeof(TargetDesc); + /** Pointer to an array of compiler option entries, whose size is compilerOptionEntryCount. + */ + CompilerOptionEntry* compilerOptionEntries = nullptr; - /** The target format to generate code for (e.g., SPIR-V, DXIL, etc.) - */ - SlangCompileTarget format = SLANG_TARGET_UNKNOWN; + /** Number of additional compiler option entries. + */ + uint32_t compilerOptionEntryCount = 0; +}; - /** The compilation profile supported by the target (e.g., "Shader Model 5.1") - */ - SlangProfileID profile = SLANG_PROFILE_UNKNOWN; +typedef uint32_t SessionFlags; +enum +{ + kSessionFlags_None = 0 +}; - /** Flags for the code generation target. Currently unused. */ - SlangTargetFlags flags = kDefaultTargetFlags; +struct PreprocessorMacroDesc +{ + const char* name; + const char* value; +}; - /** Default mode to use for floating-point operations on the target. - */ - SlangFloatingPointMode floatingPointMode = SLANG_FLOATING_POINT_MODE_DEFAULT; +struct SessionDesc +{ + /** The size of this structure, in bytes. + */ + size_t structureSize = sizeof(SessionDesc); - /** The line directive mode for output source code. - */ - SlangLineDirectiveMode lineDirectiveMode = SLANG_LINE_DIRECTIVE_MODE_DEFAULT; + /** Code generation targets to include in the session. + */ + TargetDesc const* targets = nullptr; + SlangInt targetCount = 0; - /** Whether to force `scalar` layout for glsl shader storage buffers. - */ - bool forceGLSLScalarBufferLayout = false; + /** Flags to configure the session. + */ + SessionFlags flags = kSessionFlags_None; - /** Pointer to an array of compiler option entries, whose size is compilerOptionEntryCount. - */ - CompilerOptionEntry* compilerOptionEntries = nullptr; + /** Default layout to assume for variables with matrix types. + */ + SlangMatrixLayoutMode defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_ROW_MAJOR; - /** Number of additional compiler option entries. - */ - uint32_t compilerOptionEntryCount = 0; + /** Paths to use when searching for `#include`d or `import`ed files. + */ + char const* const* searchPaths = nullptr; + SlangInt searchPathCount = 0; - }; + PreprocessorMacroDesc const* preprocessorMacros = nullptr; + SlangInt preprocessorMacroCount = 0; - typedef uint32_t SessionFlags; - enum - { - kSessionFlags_None = 0 - }; + ISlangFileSystem* fileSystem = nullptr; - struct PreprocessorMacroDesc - { - const char* name; - const char* value; - }; + bool enableEffectAnnotations = false; + bool allowGLSLSyntax = false; - struct SessionDesc - { - /** The size of this structure, in bytes. - */ - size_t structureSize = sizeof(SessionDesc); + /** Pointer to an array of compiler option entries, whose size is compilerOptionEntryCount. + */ + CompilerOptionEntry* compilerOptionEntries = nullptr; - /** Code generation targets to include in the session. - */ - TargetDesc const* targets = nullptr; - SlangInt targetCount = 0; + /** Number of additional compiler option entries. + */ + uint32_t compilerOptionEntryCount = 0; +}; - /** Flags to configure the session. - */ - SessionFlags flags = kSessionFlags_None; +enum class ContainerType +{ + None, + UnsizedArray, + StructuredBuffer, + ConstantBuffer, + ParameterBlock +}; + +/** A session provides a scope for code that is loaded. + +A session can be used to load modules of Slang source code, +and to request target-specific compiled binaries and layout +information. + +In order to be able to load code, the session owns a set +of active "search paths" for resolving `#include` directives +and `import` declrations, as well as a set of global +preprocessor definitions that will be used for all code +that gets `import`ed in the session. + +If multiple user shaders are loaded in the same session, +and import the same module (e.g., two source files do `import X`) +then there will only be one copy of `X` loaded within the session. + +In order to be able to generate target code, the session +owns a list of available compilation targets, which specify +code generation options. + +Code loaded and compiled within a session is owned by the session +and will remain resident in memory until the session is released. +Applications wishing to control the memory usage for compiled +and loaded code should use multiple sessions. +*/ +struct ISession : public ISlangUnknown +{ + SLANG_COM_INTERFACE(0x67618701, 0xd116, 0x468f, {0xab, 0x3b, 0x47, 0x4b, 0xed, 0xce, 0xe, 0x3d}) + + /** Get the global session thas was used to create this session. + */ + virtual SLANG_NO_THROW IGlobalSession* SLANG_MCALL getGlobalSession() = 0; + + /** Load a module as it would be by code using `import`. + */ + virtual SLANG_NO_THROW IModule* SLANG_MCALL + loadModule(const char* moduleName, IBlob** outDiagnostics = nullptr) = 0; + + /** Load a module from Slang source code. + */ + virtual SLANG_NO_THROW IModule* SLANG_MCALL loadModuleFromSource( + const char* moduleName, + const char* path, + slang::IBlob* source, + slang::IBlob** outDiagnostics = nullptr) = 0; + + /** Combine multiple component types to create a composite component type. + + The `componentTypes` array must contain `componentTypeCount` pointers + to component types that were loaded or created using the same session. + + The shader parameters and specialization parameters of the composite will + be the union of those in `componentTypes`. The relative order of child + component types is significant, and will affect the order in which + parameters are reflected and laid out. + + The entry-point functions of the composite will be the union of those in + `componentTypes`, and will follow the ordering of `componentTypes`. + + The requirements of the composite component type will be a subset of + those in `componentTypes`. If an entry in `componentTypes` has a requirement + that can be satisfied by another entry, then the composition will + satisfy the requirement and it will not appear as a requirement of + the composite. If multiple entries in `componentTypes` have a requirement + for the same type, then only the first such requirement will be retained + on the composite. The relative ordering of requirements on the composite + will otherwise match that of `componentTypes`. + + If any diagnostics are generated during creation of the composite, they + will be written to `outDiagnostics`. If an error is encountered, the + function will return null. + + It is an error to create a composite component type that recursively + aggregates the a single module more than once. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createCompositeComponentType( + IComponentType* const* componentTypes, + SlangInt componentTypeCount, + IComponentType** outCompositeComponentType, + ISlangBlob** outDiagnostics = nullptr) = 0; + + /** Specialize a type based on type arguments. + */ + virtual SLANG_NO_THROW TypeReflection* SLANG_MCALL specializeType( + TypeReflection* type, + SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, + ISlangBlob** outDiagnostics = nullptr) = 0; + + + /** Get the layout `type` on the chosen `target`. + */ + virtual SLANG_NO_THROW TypeLayoutReflection* SLANG_MCALL getTypeLayout( + TypeReflection* type, + SlangInt targetIndex = 0, + LayoutRules rules = LayoutRules::Default, + ISlangBlob** outDiagnostics = nullptr) = 0; + + /** Get a container type from `elementType`. For example, given type `T`, returns + a type that represents `StructuredBuffer`. + + @param `elementType`: the element type to wrap around. + @param `containerType`: the type of the container to wrap `elementType` in. + @param `outDiagnostics`: a blob to receive diagnostic messages. + */ + virtual SLANG_NO_THROW TypeReflection* SLANG_MCALL getContainerType( + TypeReflection* elementType, + ContainerType containerType, + ISlangBlob** outDiagnostics = nullptr) = 0; + + /** Return a `TypeReflection` that represents the `__Dynamic` type. + This type can be used as a specialization argument to indicate using + dynamic dispatch. + */ + virtual SLANG_NO_THROW TypeReflection* SLANG_MCALL getDynamicType() = 0; + + /** Get the mangled name for a type RTTI object. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getTypeRTTIMangledName(TypeReflection* type, ISlangBlob** outNameBlob) = 0; + + /** Get the mangled name for a type witness. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTypeConformanceWitnessMangledName( + TypeReflection* type, + TypeReflection* interfaceType, + ISlangBlob** outNameBlob) = 0; + + /** Get the sequential ID used to identify a type witness in a dynamic object. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTypeConformanceWitnessSequentialID( + slang::TypeReflection* type, + slang::TypeReflection* interfaceType, + uint32_t* outId) = 0; + + /** Create a request to load/compile front-end code. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + createCompileRequest(SlangCompileRequest** outCompileRequest) = 0; + + + /** Creates a `IComponentType` that represents a type's conformance to an interface. + The retrieved `ITypeConformance` objects can be included in a composite `IComponentType` + to explicitly specify which implementation types should be included in the final compiled + code. For example, if an module defines `IMaterial` interface and `AMaterial`, + `BMaterial`, `CMaterial` types that implements the interface, the user can exclude + `CMaterial` implementation from the resulting shader code by explcitly adding + `AMaterial:IMaterial` and `BMaterial:IMaterial` conformances to a composite + `IComponentType` and get entry point code from it. The resulting code will not have + anything related to `CMaterial` in the dynamic dispatch logic. If the user does not + explicitly include any `TypeConformances` to an interface type, all implementations to + that interface will be included by default. By linking a `ITypeConformance`, the user is + also given the opportunity to specify the dispatch ID of the implementation type. If + `conformanceIdOverride` is -1, there will be no override behavior and Slang will + automatically assign IDs to implementation types. The automatically assigned IDs can be + queried via `ISession::getTypeConformanceWitnessSequentialID`. + + Returns SLANG_OK if succeeds, or SLANG_FAIL if `type` does not conform to `interfaceType`. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createTypeConformanceComponentType( + slang::TypeReflection* type, + slang::TypeReflection* interfaceType, + ITypeConformance** outConformance, + SlangInt conformanceIdOverride, + ISlangBlob** outDiagnostics) = 0; + + /** Load a module from a Slang module blob. + */ + virtual SLANG_NO_THROW IModule* SLANG_MCALL loadModuleFromIRBlob( + const char* moduleName, + const char* path, + slang::IBlob* source, + slang::IBlob** outDiagnostics = nullptr) = 0; + + virtual SLANG_NO_THROW SlangInt SLANG_MCALL getLoadedModuleCount() = 0; + virtual SLANG_NO_THROW IModule* SLANG_MCALL getLoadedModule(SlangInt index) = 0; + + /** Checks if a precompiled binary module is up-to-date with the current compiler + * option settings and the source file contents. + */ + virtual SLANG_NO_THROW bool SLANG_MCALL + isBinaryModuleUpToDate(const char* modulePath, slang::IBlob* binaryModuleBlob) = 0; + + /** Load a module from a string. + */ + virtual SLANG_NO_THROW IModule* SLANG_MCALL loadModuleFromSourceString( + const char* moduleName, + const char* path, + const char* string, + slang::IBlob** outDiagnostics = nullptr) = 0; +}; - /** Default layout to assume for variables with matrix types. - */ - SlangMatrixLayoutMode defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_ROW_MAJOR; + #define SLANG_UUID_ISession ISession::getTypeGuid() - /** Paths to use when searching for `#include`d or `import`ed files. - */ - char const* const* searchPaths = nullptr; - SlangInt searchPathCount = 0; +struct IMetadata : public ISlangCastable +{ + SLANG_COM_INTERFACE(0x8044a8a3, 0xddc0, 0x4b7f, {0xaf, 0x8e, 0x2, 0x6e, 0x90, 0x5d, 0x73, 0x32}) - PreprocessorMacroDesc const* preprocessorMacros = nullptr; - SlangInt preprocessorMacroCount = 0; + /* + Returns whether a resource parameter at the specifieid binding location is actually being used + in the compiled shader. + */ + virtual SlangResult isParameterLocationUsed( + SlangParameterCategory category, // is this a `t` register? `s` register? + SlangUInt spaceIndex, // `space` for D3D12, `set` for Vulkan + SlangUInt registerIndex, // `register` for D3D12, `binding` for Vulkan + bool& outUsed) = 0; +}; + #define SLANG_UUID_IMetadata IMetadata::getTypeGuid() - ISlangFileSystem* fileSystem = nullptr; +/** A component type is a unit of shader code layout, reflection, and linking. - bool enableEffectAnnotations = false; - bool allowGLSLSyntax = false; +A component type is a unit of shader code that can be included into +a linked and compiled shader program. Each component type may have: - /** Pointer to an array of compiler option entries, whose size is compilerOptionEntryCount. - */ - CompilerOptionEntry* compilerOptionEntries = nullptr; +* Zero or more uniform shader parameters, representing textures, + buffers, etc. that the code in the component depends on. - /** Number of additional compiler option entries. - */ - uint32_t compilerOptionEntryCount = 0; +* Zero or more *specialization* parameters, which are type or + value parameters that can be used to synthesize specialized + versions of the component type. - }; +* Zero or more entry points, which are the individually invocable + kernels that can have final code generated. - enum class ContainerType - { - None, UnsizedArray, StructuredBuffer, ConstantBuffer, ParameterBlock - }; +* Zero or more *requirements*, which are other component + types on which the component type depends. - /** A session provides a scope for code that is loaded. +One example of a component type is a module of Slang code: - A session can be used to load modules of Slang source code, - and to request target-specific compiled binaries and layout - information. +* The global-scope shader parameters declared in the module are + the parameters when considered as a component type. - In order to be able to load code, the session owns a set - of active "search paths" for resolving `#include` directives - and `import` declrations, as well as a set of global - preprocessor definitions that will be used for all code - that gets `import`ed in the session. +* Any global-scope generic or interface type parameters introduce + specialization parameters for the module. - If multiple user shaders are loaded in the same session, - and import the same module (e.g., two source files do `import X`) - then there will only be one copy of `X` loaded within the session. +* A module does not by default include any entry points when + considered as a component type (although the code of the + module might *declare* some entry points). - In order to be able to generate target code, the session - owns a list of available compilation targets, which specify - code generation options. +* Any other modules that are `import`ed in the source code + become requirements of the module, when considered as a + component type. - Code loaded and compiled within a session is owned by the session - and will remain resident in memory until the session is released. - Applications wishing to control the memory usage for compiled - and loaded code should use multiple sessions. - */ - struct ISession : public ISlangUnknown - { - SLANG_COM_INTERFACE( 0x67618701, 0xd116, 0x468f, { 0xab, 0x3b, 0x47, 0x4b, 0xed, 0xce, 0xe, 0x3d } ) +An entry point is another example of a component type: - /** Get the global session thas was used to create this session. - */ - virtual SLANG_NO_THROW IGlobalSession* SLANG_MCALL getGlobalSession() = 0; +* The `uniform` parameters of the entry point function are + its shader parameters when considered as a component type. - /** Load a module as it would be by code using `import`. - */ - virtual SLANG_NO_THROW IModule* SLANG_MCALL loadModule( - const char* moduleName, - IBlob** outDiagnostics = nullptr) = 0; +* Any generic or interface-type parameters of the entry point + introduce specialization parameters. - /** Load a module from Slang source code. - */ - virtual SLANG_NO_THROW IModule* SLANG_MCALL loadModuleFromSource( - const char* moduleName, - const char* path, - slang::IBlob* source, - slang::IBlob** outDiagnostics = nullptr) = 0; - - /** Combine multiple component types to create a composite component type. - - The `componentTypes` array must contain `componentTypeCount` pointers - to component types that were loaded or created using the same session. - - The shader parameters and specialization parameters of the composite will - be the union of those in `componentTypes`. The relative order of child - component types is significant, and will affect the order in which - parameters are reflected and laid out. - - The entry-point functions of the composite will be the union of those in - `componentTypes`, and will follow the ordering of `componentTypes`. - - The requirements of the composite component type will be a subset of - those in `componentTypes`. If an entry in `componentTypes` has a requirement - that can be satisfied by another entry, then the composition will - satisfy the requirement and it will not appear as a requirement of - the composite. If multiple entries in `componentTypes` have a requirement - for the same type, then only the first such requirement will be retained - on the composite. The relative ordering of requirements on the composite - will otherwise match that of `componentTypes`. - - If any diagnostics are generated during creation of the composite, they - will be written to `outDiagnostics`. If an error is encountered, the - function will return null. - - It is an error to create a composite component type that recursively - aggregates the a single module more than once. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createCompositeComponentType( - IComponentType* const* componentTypes, - SlangInt componentTypeCount, - IComponentType** outCompositeComponentType, - ISlangBlob** outDiagnostics = nullptr) = 0; - - /** Specialize a type based on type arguments. - */ - virtual SLANG_NO_THROW TypeReflection* SLANG_MCALL specializeType( - TypeReflection* type, - SpecializationArg const* specializationArgs, - SlangInt specializationArgCount, - ISlangBlob** outDiagnostics = nullptr) = 0; - - - /** Get the layout `type` on the chosen `target`. - */ - virtual SLANG_NO_THROW TypeLayoutReflection* SLANG_MCALL getTypeLayout( - TypeReflection* type, - SlangInt targetIndex = 0, - LayoutRules rules = LayoutRules::Default, - ISlangBlob** outDiagnostics = nullptr) = 0; - - /** Get a container type from `elementType`. For example, given type `T`, returns - a type that represents `StructuredBuffer`. - - @param `elementType`: the element type to wrap around. - @param `containerType`: the type of the container to wrap `elementType` in. - @param `outDiagnostics`: a blob to receive diagnostic messages. - */ - virtual SLANG_NO_THROW TypeReflection* SLANG_MCALL getContainerType( - TypeReflection* elementType, - ContainerType containerType, - ISlangBlob** outDiagnostics = nullptr) = 0; - - /** Return a `TypeReflection` that represents the `__Dynamic` type. - This type can be used as a specialization argument to indicate using - dynamic dispatch. - */ - virtual SLANG_NO_THROW TypeReflection* SLANG_MCALL getDynamicType() = 0; - - /** Get the mangled name for a type RTTI object. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTypeRTTIMangledName( - TypeReflection* type, - ISlangBlob** outNameBlob) = 0; - - /** Get the mangled name for a type witness. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTypeConformanceWitnessMangledName( - TypeReflection* type, - TypeReflection* interfaceType, - ISlangBlob** outNameBlob) = 0; - - /** Get the sequential ID used to identify a type witness in a dynamic object. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTypeConformanceWitnessSequentialID( - slang::TypeReflection* type, - slang::TypeReflection* interfaceType, - uint32_t* outId) = 0; - - /** Create a request to load/compile front-end code. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createCompileRequest( - SlangCompileRequest** outCompileRequest) = 0; - - - /** Creates a `IComponentType` that represents a type's conformance to an interface. - The retrieved `ITypeConformance` objects can be included in a composite `IComponentType` - to explicitly specify which implementation types should be included in the final compiled - code. For example, if an module defines `IMaterial` interface and `AMaterial`, - `BMaterial`, `CMaterial` types that implements the interface, the user can exclude - `CMaterial` implementation from the resulting shader code by explcitly adding - `AMaterial:IMaterial` and `BMaterial:IMaterial` conformances to a composite - `IComponentType` and get entry point code from it. The resulting code will not have - anything related to `CMaterial` in the dynamic dispatch logic. If the user does not - explicitly include any `TypeConformances` to an interface type, all implementations to - that interface will be included by default. By linking a `ITypeConformance`, the user is - also given the opportunity to specify the dispatch ID of the implementation type. If - `conformanceIdOverride` is -1, there will be no override behavior and Slang will - automatically assign IDs to implementation types. The automatically assigned IDs can be - queried via `ISession::getTypeConformanceWitnessSequentialID`. - - Returns SLANG_OK if succeeds, or SLANG_FAIL if `type` does not conform to `interfaceType`. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createTypeConformanceComponentType( - slang::TypeReflection* type, - slang::TypeReflection* interfaceType, - ITypeConformance** outConformance, - SlangInt conformanceIdOverride, - ISlangBlob** outDiagnostics) = 0; - - /** Load a module from a Slang module blob. - */ - virtual SLANG_NO_THROW IModule* SLANG_MCALL loadModuleFromIRBlob( - const char* moduleName, - const char* path, - slang::IBlob* source, - slang::IBlob** outDiagnostics = nullptr) = 0; - - virtual SLANG_NO_THROW SlangInt SLANG_MCALL getLoadedModuleCount() = 0; - virtual SLANG_NO_THROW IModule* SLANG_MCALL getLoadedModule(SlangInt index) = 0; - - /** Checks if a precompiled binary module is up-to-date with the current compiler - * option settings and the source file contents. - */ - virtual SLANG_NO_THROW bool SLANG_MCALL isBinaryModuleUpToDate( - const char* modulePath, slang::IBlob* binaryModuleBlob) = 0; - - /** Load a module from a string. - */ - virtual SLANG_NO_THROW IModule* SLANG_MCALL loadModuleFromSourceString( - const char* moduleName, - const char* path, - const char* string, - slang::IBlob** outDiagnostics = nullptr) = 0; - }; +* An entry point component type exposes a single entry point (itself). - #define SLANG_UUID_ISession ISession::getTypeGuid() +* An entry point has one requirement for the module in which + it was defined. - struct IMetadata : public ISlangCastable - { - SLANG_COM_INTERFACE(0x8044a8a3, 0xddc0, 0x4b7f, { 0xaf, 0x8e, 0x2, 0x6e, 0x90, 0x5d, 0x73, 0x32 }) +Component types can be manipulated in a few ways: - /* - Returns whether a resource parameter at the specifieid binding location is actually being used - in the compiled shader. - */ - virtual SlangResult isParameterLocationUsed( - SlangParameterCategory category, // is this a `t` register? `s` register? - SlangUInt spaceIndex, // `space` for D3D12, `set` for Vulkan - SlangUInt registerIndex, // `register` for D3D12, `binding` for Vulkan - bool& outUsed) = 0; - }; - #define SLANG_UUID_IMetadata IMetadata::getTypeGuid() +* Multiple component types can be combined into a composite, which + combines all of their code, parameters, etc. - /** A component type is a unit of shader code layout, reflection, and linking. +* A component type can be specialized, by "plugging in" types and + values for its specialization parameters. - A component type is a unit of shader code that can be included into - a linked and compiled shader program. Each component type may have: +* A component type can be laid out for a particular target, giving + offsets/bindings to the shader parameters it contains. - * Zero or more uniform shader parameters, representing textures, - buffers, etc. that the code in the component depends on. +* Generated kernel code can be requested for entry points. - * Zero or more *specialization* parameters, which are type or - value parameters that can be used to synthesize specialized - versions of the component type. +*/ +struct IComponentType : public ISlangUnknown +{ + SLANG_COM_INTERFACE(0x5bc42be8, 0x5c50, 0x4929, {0x9e, 0x5e, 0xd1, 0x5e, 0x7c, 0x24, 0x1, 0x5f}) + + /** Get the runtime session that this component type belongs to. + */ + virtual SLANG_NO_THROW ISession* SLANG_MCALL getSession() = 0; + + /** Get the layout for this program for the chosen `targetIndex`. + + The resulting layout will establish offsets/bindings for all + of the global and entry-point shader parameters in the + component type. + + If this component type has specialization parameters (that is, + it is not fully specialized), then the resulting layout may + be incomplete, and plugging in arguments for generic specialization + parameters may result in a component type that doesn't have + a compatible layout. If the component type only uses + interface-type specialization parameters, then the layout + for a specialization should be compatible with an unspecialized + layout (all parameters in the unspecialized layout will have + the same offset/binding in the specialized layout). + + If this component type is combined into a composite, then + the absolute offsets/bindings of parameters may not stay the same. + If the shader parameters in a component type don't make + use of explicit binding annotations (e.g., `register(...)`), + then the *relative* offset of shader parameters will stay + the same when it is used in a composition. + */ + virtual SLANG_NO_THROW ProgramLayout* SLANG_MCALL + getLayout(SlangInt targetIndex = 0, IBlob** outDiagnostics = nullptr) = 0; - * Zero or more entry points, which are the individually invocable - kernels that can have final code generated. + /** Get the number of (unspecialized) specialization parameters for the component type. + */ + virtual SLANG_NO_THROW SlangInt SLANG_MCALL getSpecializationParamCount() = 0; - * Zero or more *requirements*, which are other component - types on which the component type depends. + /** Get the compiled code for the entry point at `entryPointIndex` for the chosen `targetIndex` - One example of a component type is a module of Slang code: + Entry point code can only be computed for a component type that + has no specialization parameters (it must be fully specialized) + and that has no requirements (it must be fully linked). - * The global-scope shader parameters declared in the module are - the parameters when considered as a component type. + If code has not already been generated for the given entry point and target, + then a compilation error may be detected, in which case `outDiagnostics` + (if non-null) will be filled in with a blob of messages diagnosing the error. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointCode( + SlangInt entryPointIndex, + SlangInt targetIndex, + IBlob** outCode, + IBlob** outDiagnostics = nullptr) = 0; - * Any global-scope generic or interface type parameters introduce - specialization parameters for the module. + /** Get the compilation result as a file system. - * A module does not by default include any entry points when - considered as a component type (although the code of the - module might *declare* some entry points). + Has the same requirements as getEntryPointCode. - * Any other modules that are `import`ed in the source code - become requirements of the module, when considered as a - component type. + The result is not written to the actual OS file system, but is made avaiable as an + in memory representation. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getResultAsFileSystem( + SlangInt entryPointIndex, + SlangInt targetIndex, + ISlangMutableFileSystem** outFileSystem) = 0; - An entry point is another example of a component type: + /** Compute a hash for the entry point at `entryPointIndex` for the chosen `targetIndex`. - * The `uniform` parameters of the entry point function are - its shader parameters when considered as a component type. + This computes a hash based on all the dependencies for this component type as well as the + target settings affecting the compiler backend. The computed hash is used as a key for caching + the output of the compiler backend to implement shader caching. + */ + virtual SLANG_NO_THROW void SLANG_MCALL + getEntryPointHash(SlangInt entryPointIndex, SlangInt targetIndex, IBlob** outHash) = 0; - * Any generic or interface-type parameters of the entry point - introduce specialization parameters. + /** Specialize the component by binding its specialization parameters to concrete arguments. - * An entry point component type exposes a single entry point (itself). + The `specializationArgs` array must have `specializationArgCount` entries, and + this must match the number of specialization parameters on this component type. - * An entry point has one requirement for the module in which - it was defined. + If any diagnostics (error or warnings) are produced, they will be written to `outDiagnostics`. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL specialize( + SpecializationArg const* specializationArgs, + SlangInt specializationArgCount, + IComponentType** outSpecializedComponentType, + ISlangBlob** outDiagnostics = nullptr) = 0; + + /** Link this component type against all of its unsatisifed dependencies. + + A component type may have unsatisfied dependencies. For example, a module + depends on any other modules it `import`s, and an entry point depends + on the module that defined it. + + A user can manually satisfy dependencies by creating a composite + component type, and when doing so they retain full control over + the relative ordering of shader parameters in the resulting layout. + + It is an error to try to generate/access compiled kernel code for + a component type with unresolved dependencies, so if dependencies + remain after whatever manual composition steps an application + cares to peform, the `link()` function can be used to automatically + compose in any remaining dependencies. The order of parameters + (and hence the global layout) that results will be deterministic, + but is not currently documented. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + link(IComponentType** outLinkedComponentType, ISlangBlob** outDiagnostics = nullptr) = 0; - Component types can be manipulated in a few ways: + /** Get entry point 'callable' functions accessible through the ISlangSharedLibrary interface. - * Multiple component types can be combined into a composite, which - combines all of their code, parameters, etc. + The functions remain in scope as long as the ISlangSharedLibrary interface is in scope. - * A component type can be specialized, by "plugging in" types and - values for its specialization parameters. + NOTE! Requires a compilation target of SLANG_HOST_CALLABLE. - * A component type can be laid out for a particular target, giving - offsets/bindings to the shader parameters it contains. + @param entryPointIndex The index of the entry point to get code for. + @param targetIndex The index of the target to get code for (default: zero). + @param outSharedLibrary A pointer to a ISharedLibrary interface which functions can be queried + on. + @returns A `SlangResult` to indicate success or failure. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointHostCallable( + int entryPointIndex, + int targetIndex, + ISlangSharedLibrary** outSharedLibrary, + slang::IBlob** outDiagnostics = 0) = 0; - * Generated kernel code can be requested for entry points. + /** Get a new ComponentType object that represents a renamed entry point. - */ - struct IComponentType : public ISlangUnknown - { - SLANG_COM_INTERFACE(0x5bc42be8, 0x5c50, 0x4929, { 0x9e, 0x5e, 0xd1, 0x5e, 0x7c, 0x24, 0x1, 0x5f }) - - /** Get the runtime session that this component type belongs to. - */ - virtual SLANG_NO_THROW ISession* SLANG_MCALL getSession() = 0; - - /** Get the layout for this program for the chosen `targetIndex`. - - The resulting layout will establish offsets/bindings for all - of the global and entry-point shader parameters in the - component type. - - If this component type has specialization parameters (that is, - it is not fully specialized), then the resulting layout may - be incomplete, and plugging in arguments for generic specialization - parameters may result in a component type that doesn't have - a compatible layout. If the component type only uses - interface-type specialization parameters, then the layout - for a specialization should be compatible with an unspecialized - layout (all parameters in the unspecialized layout will have - the same offset/binding in the specialized layout). - - If this component type is combined into a composite, then - the absolute offsets/bindings of parameters may not stay the same. - If the shader parameters in a component type don't make - use of explicit binding annotations (e.g., `register(...)`), - then the *relative* offset of shader parameters will stay - the same when it is used in a composition. - */ - virtual SLANG_NO_THROW ProgramLayout* SLANG_MCALL getLayout( - SlangInt targetIndex = 0, - IBlob** outDiagnostics = nullptr) = 0; - - /** Get the number of (unspecialized) specialization parameters for the component type. - */ - virtual SLANG_NO_THROW SlangInt SLANG_MCALL getSpecializationParamCount() = 0; - - /** Get the compiled code for the entry point at `entryPointIndex` for the chosen `targetIndex` - - Entry point code can only be computed for a component type that - has no specialization parameters (it must be fully specialized) - and that has no requirements (it must be fully linked). - - If code has not already been generated for the given entry point and target, - then a compilation error may be detected, in which case `outDiagnostics` - (if non-null) will be filled in with a blob of messages diagnosing the error. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointCode( - SlangInt entryPointIndex, - SlangInt targetIndex, - IBlob** outCode, - IBlob** outDiagnostics = nullptr) = 0; - - /** Get the compilation result as a file system. - - Has the same requirements as getEntryPointCode. - - The result is not written to the actual OS file system, but is made avaiable as an - in memory representation. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getResultAsFileSystem( - SlangInt entryPointIndex, - SlangInt targetIndex, - ISlangMutableFileSystem** outFileSystem) = 0; - - /** Compute a hash for the entry point at `entryPointIndex` for the chosen `targetIndex`. - - This computes a hash based on all the dependencies for this component type as well as the - target settings affecting the compiler backend. The computed hash is used as a key for caching - the output of the compiler backend to implement shader caching. - */ - virtual SLANG_NO_THROW void SLANG_MCALL getEntryPointHash( - SlangInt entryPointIndex, - SlangInt targetIndex, - IBlob** outHash) = 0; - - /** Specialize the component by binding its specialization parameters to concrete arguments. - - The `specializationArgs` array must have `specializationArgCount` entries, and - this must match the number of specialization parameters on this component type. - - If any diagnostics (error or warnings) are produced, they will be written to `outDiagnostics`. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL specialize( - SpecializationArg const* specializationArgs, - SlangInt specializationArgCount, - IComponentType** outSpecializedComponentType, - ISlangBlob** outDiagnostics = nullptr) = 0; - - /** Link this component type against all of its unsatisifed dependencies. - - A component type may have unsatisfied dependencies. For example, a module - depends on any other modules it `import`s, and an entry point depends - on the module that defined it. - - A user can manually satisfy dependencies by creating a composite - component type, and when doing so they retain full control over - the relative ordering of shader parameters in the resulting layout. - - It is an error to try to generate/access compiled kernel code for - a component type with unresolved dependencies, so if dependencies - remain after whatever manual composition steps an application - cares to peform, the `link()` function can be used to automatically - compose in any remaining dependencies. The order of parameters - (and hence the global layout) that results will be deterministic, - but is not currently documented. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL link( - IComponentType** outLinkedComponentType, - ISlangBlob** outDiagnostics = nullptr) = 0; - - /** Get entry point 'callable' functions accessible through the ISlangSharedLibrary interface. - - The functions remain in scope as long as the ISlangSharedLibrary interface is in scope. - - NOTE! Requires a compilation target of SLANG_HOST_CALLABLE. - - @param entryPointIndex The index of the entry point to get code for. - @param targetIndex The index of the target to get code for (default: zero). - @param outSharedLibrary A pointer to a ISharedLibrary interface which functions can be queried on. - @returns A `SlangResult` to indicate success or failure. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointHostCallable( - int entryPointIndex, - int targetIndex, - ISlangSharedLibrary** outSharedLibrary, - slang::IBlob** outDiagnostics = 0) = 0; - - /** Get a new ComponentType object that represents a renamed entry point. - - The current object must be a single EntryPoint, or a CompositeComponentType or - SpecializedComponentType that contains one EntryPoint component. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL renameEntryPoint( - const char* newName, IComponentType** outEntryPoint) = 0; - - /** Link and specify additional compiler options when generating code - * from the linked program. - */ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL linkWithOptions( - IComponentType** outLinkedComponentType, - uint32_t compilerOptionEntryCount, - CompilerOptionEntry* compilerOptionEntries, - ISlangBlob** outDiagnostics = nullptr) = 0; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTargetCode( - SlangInt targetIndex, - IBlob** outCode, - IBlob** outDiagnostics = nullptr) = 0; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTargetMetadata( - SlangInt targetIndex, - IMetadata** outMetadata, - IBlob** outDiagnostics = nullptr) = 0; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointMetadata( - SlangInt entryPointIndex, - SlangInt targetIndex, - IMetadata** outMetadata, - IBlob** outDiagnostics = nullptr) = 0; - }; + The current object must be a single EntryPoint, or a CompositeComponentType or + SpecializedComponentType that contains one EntryPoint component. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + renameEntryPoint(const char* newName, IComponentType** outEntryPoint) = 0; + + /** Link and specify additional compiler options when generating code + * from the linked program. + */ + virtual SLANG_NO_THROW SlangResult SLANG_MCALL linkWithOptions( + IComponentType** outLinkedComponentType, + uint32_t compilerOptionEntryCount, + CompilerOptionEntry* compilerOptionEntries, + ISlangBlob** outDiagnostics = nullptr) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getTargetCode(SlangInt targetIndex, IBlob** outCode, IBlob** outDiagnostics = nullptr) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getTargetMetadata( + SlangInt targetIndex, + IMetadata** outMetadata, + IBlob** outDiagnostics = nullptr) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getEntryPointMetadata( + SlangInt entryPointIndex, + SlangInt targetIndex, + IMetadata** outMetadata, + IBlob** outDiagnostics = nullptr) = 0; +}; #define SLANG_UUID_IComponentType IComponentType::getTypeGuid() - struct IEntryPoint : public IComponentType - { - SLANG_COM_INTERFACE(0x8f241361, 0xf5bd, 0x4ca0, { 0xa3, 0xac, 0x2, 0xf7, 0xfa, 0x24, 0x2, 0xb8 }) +struct IEntryPoint : public IComponentType +{ + SLANG_COM_INTERFACE(0x8f241361, 0xf5bd, 0x4ca0, {0xa3, 0xac, 0x2, 0xf7, 0xfa, 0x24, 0x2, 0xb8}) - virtual SLANG_NO_THROW FunctionReflection* SLANG_MCALL getFunctionReflection() = 0; - }; + virtual SLANG_NO_THROW FunctionReflection* SLANG_MCALL getFunctionReflection() = 0; +}; #define SLANG_UUID_IEntryPoint IEntryPoint::getTypeGuid() - struct ITypeConformance : public IComponentType - { - SLANG_COM_INTERFACE(0x73eb3147, 0xe544, 0x41b5, { 0xb8, 0xf0, 0xa2, 0x44, 0xdf, 0x21, 0x94, 0xb }) - }; +struct ITypeConformance : public IComponentType +{ + SLANG_COM_INTERFACE(0x73eb3147, 0xe544, 0x41b5, {0xb8, 0xf0, 0xa2, 0x44, 0xdf, 0x21, 0x94, 0xb}) +}; #define SLANG_UUID_ITypeConformance ITypeConformance::getTypeGuid() - /** A module is the granularity of shader code compilation and loading. +/** A module is the granularity of shader code compilation and loading. - In most cases a module corresponds to a single compile "translation unit." - This will often be a single `.slang` or `.hlsl` file and everything it - `#include`s. +In most cases a module corresponds to a single compile "translation unit." +This will often be a single `.slang` or `.hlsl` file and everything it +`#include`s. - Notably, a module `M` does *not* include the things it `import`s, as these - as distinct modules that `M` depends on. There is a directed graph of - module dependencies, and all modules in the graph must belong to the - same session (`ISession`). +Notably, a module `M` does *not* include the things it `import`s, as these +as distinct modules that `M` depends on. There is a directed graph of +module dependencies, and all modules in the graph must belong to the +same session (`ISession`). - A module establishes a namespace for looking up types, functions, etc. - */ - struct IModule : public IComponentType - { - SLANG_COM_INTERFACE(0xc720e64, 0x8722, 0x4d31, { 0x89, 0x90, 0x63, 0x8a, 0x98, 0xb1, 0xc2, 0x79 }) +A module establishes a namespace for looking up types, functions, etc. +*/ +struct IModule : public IComponentType +{ + SLANG_COM_INTERFACE(0xc720e64, 0x8722, 0x4d31, {0x89, 0x90, 0x63, 0x8a, 0x98, 0xb1, 0xc2, 0x79}) - virtual SLANG_NO_THROW SlangResult SLANG_MCALL findEntryPointByName( - char const* name, - IEntryPoint** outEntryPoint) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + findEntryPointByName(char const* name, IEntryPoint** outEntryPoint) = 0; - /// Get number of entry points defined in the module. An entry point defined in a module - /// is by default not included in the linkage, so calls to `IComponentType::getEntryPointCount` - /// on an `IModule` instance will always return 0. However `IModule::getDefinedEntryPointCount` - /// will return the number of defined entry points. - virtual SLANG_NO_THROW SlangInt32 SLANG_MCALL getDefinedEntryPointCount() = 0; - /// Get the name of an entry point defined in the module. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL - getDefinedEntryPoint(SlangInt32 index, IEntryPoint** outEntryPoint) = 0; + /// Get number of entry points defined in the module. An entry point defined in a module + /// is by default not included in the linkage, so calls to `IComponentType::getEntryPointCount` + /// on an `IModule` instance will always return 0. However `IModule::getDefinedEntryPointCount` + /// will return the number of defined entry points. + virtual SLANG_NO_THROW SlangInt32 SLANG_MCALL getDefinedEntryPointCount() = 0; + /// Get the name of an entry point defined in the module. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getDefinedEntryPoint(SlangInt32 index, IEntryPoint** outEntryPoint) = 0; - /// Get a serialized representation of the checked module. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL serialize(ISlangBlob** outSerializedBlob) = 0; + /// Get a serialized representation of the checked module. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL serialize(ISlangBlob** outSerializedBlob) = 0; - /// Write the serialized representation of this module to a file. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL writeToFile(char const* fileName) = 0; + /// Write the serialized representation of this module to a file. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL writeToFile(char const* fileName) = 0; - /// Get the name of the module. - virtual SLANG_NO_THROW const char* SLANG_MCALL getName() = 0; + /// Get the name of the module. + virtual SLANG_NO_THROW const char* SLANG_MCALL getName() = 0; - /// Get the path of the module. - virtual SLANG_NO_THROW const char* SLANG_MCALL getFilePath() = 0; + /// Get the path of the module. + virtual SLANG_NO_THROW const char* SLANG_MCALL getFilePath() = 0; - /// Get the unique identity of the module. - virtual SLANG_NO_THROW const char* SLANG_MCALL getUniqueIdentity() = 0; + /// Get the unique identity of the module. + virtual SLANG_NO_THROW const char* SLANG_MCALL getUniqueIdentity() = 0; - /// Find and validate an entry point by name, even if the function is - /// not marked with the `[shader("...")]` attribute. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL findAndCheckEntryPoint( - char const* name, - SlangStage stage, - IEntryPoint** outEntryPoint, - ISlangBlob** outDiagnostics) = 0; + /// Find and validate an entry point by name, even if the function is + /// not marked with the `[shader("...")]` attribute. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL findAndCheckEntryPoint( + char const* name, + SlangStage stage, + IEntryPoint** outEntryPoint, + ISlangBlob** outDiagnostics) = 0; - /// Get the number of dependency files that this module depends on. - /// This includes both the explicit source files, as well as any - /// additional files that were transitively referenced (e.g., via - /// a `#include` directive). - virtual SLANG_NO_THROW SlangInt32 SLANG_MCALL getDependencyFileCount() = 0; + /// Get the number of dependency files that this module depends on. + /// This includes both the explicit source files, as well as any + /// additional files that were transitively referenced (e.g., via + /// a `#include` directive). + virtual SLANG_NO_THROW SlangInt32 SLANG_MCALL getDependencyFileCount() = 0; - /// Get the path to a file this module depends on. - virtual SLANG_NO_THROW char const* SLANG_MCALL getDependencyFilePath( - SlangInt32 index) = 0; + /// Get the path to a file this module depends on. + virtual SLANG_NO_THROW char const* SLANG_MCALL getDependencyFilePath(SlangInt32 index) = 0; + + virtual SLANG_NO_THROW DeclReflection* SLANG_MCALL getModuleReflection() = 0; +}; - virtual SLANG_NO_THROW DeclReflection* SLANG_MCALL getModuleReflection() = 0; - }; - #define SLANG_UUID_IModule IModule::getTypeGuid() - /* Experimental interface for doing target precompilation of slang modules */ - struct IModulePrecompileService_Experimental : public ISlangUnknown - { - //uuidgen output: 8e12e8e3 - 5fcd - 433e - afcb - 13a088bc5ee5 - SLANG_COM_INTERFACE(0x8e12e8e3, 0x5fcd, 0x433e, { 0xaf, 0xcb, 0x13, 0xa0, 0x88, 0xbc, 0x5e, 0xe5 }) +/* Experimental interface for doing target precompilation of slang modules */ +struct IModulePrecompileService_Experimental : public ISlangUnknown +{ + // uuidgen output: 8e12e8e3 - 5fcd - 433e - afcb - 13a088bc5ee5 + SLANG_COM_INTERFACE( + 0x8e12e8e3, + 0x5fcd, + 0x433e, + {0xaf, 0xcb, 0x13, 0xa0, 0x88, 0xbc, 0x5e, 0xe5}) - virtual SLANG_NO_THROW SlangResult SLANG_MCALL precompileForTarget( - SlangCompileTarget target, - ISlangBlob** outDiagnostics) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + precompileForTarget(SlangCompileTarget target, ISlangBlob** outDiagnostics) = 0; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPrecompiledTargetCode( - SlangCompileTarget target, - IBlob** outCode, - IBlob** outDiagnostics = nullptr) = 0; - - virtual SLANG_NO_THROW SlangInt SLANG_MCALL getModuleDependencyCount() = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getPrecompiledTargetCode( + SlangCompileTarget target, + IBlob** outCode, + IBlob** outDiagnostics = nullptr) = 0; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getModuleDependency( - SlangInt dependencyIndex, - IModule** outModule, - IBlob** outDiagnostics = nullptr) = 0; - }; + virtual SLANG_NO_THROW SlangInt SLANG_MCALL getModuleDependencyCount() = 0; - #define SLANG_UUID_IModulePrecompileService_Experimental IModulePrecompileService_Experimental::getTypeGuid() + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getModuleDependency( + SlangInt dependencyIndex, + IModule** outModule, + IBlob** outDiagnostics = nullptr) = 0; +}; - /** Argument used for specialization to types/values. - */ - struct SpecializationArg - { - enum class Kind : int32_t - { - Unknown, /**< An invalid specialization argument. */ - Type, /**< Specialize to a type. */ - }; + #define SLANG_UUID_IModulePrecompileService_Experimental \ + IModulePrecompileService_Experimental::getTypeGuid() - /** The kind of specialization argument. */ - Kind kind; - union - { - /** A type specialization argument, used for `Kind::Type`. */ - TypeReflection* type; - }; +/** Argument used for specialization to types/values. + */ +struct SpecializationArg +{ + enum class Kind : int32_t + { + Unknown, /**< An invalid specialization argument. */ + Type, /**< Specialize to a type. */ + }; - static SpecializationArg fromType(TypeReflection* inType) - { - SpecializationArg rs; - rs.kind = Kind::Type; - rs.type = inType; - return rs; - } + /** The kind of specialization argument. */ + Kind kind; + union + { + /** A type specialization argument, used for `Kind::Type`. */ + TypeReflection* type; }; -} -// Passed into functions to create globalSession to identify the API version client code is -// using. -#define SLANG_API_VERSION 0 + static SpecializationArg fromType(TypeReflection* inType) + { + SpecializationArg rs; + rs.kind = Kind::Type; + rs.type = inType; + return rs; + } +}; +} // namespace slang + + // Passed into functions to create globalSession to identify the API version client code is + // using. + #define SLANG_API_VERSION 0 /* Create a global session, with the built-in core module. @param apiVersion Pass in SLANG_API_VERSION -@param outGlobalSession (out)The created global session. +@param outGlobalSession (out)The created global session. */ -SLANG_EXTERN_C SLANG_API SlangResult slang_createGlobalSession( - SlangInt apiVersion, - slang::IGlobalSession** outGlobalSession); +SLANG_EXTERN_C SLANG_API SlangResult +slang_createGlobalSession(SlangInt apiVersion, slang::IGlobalSession** outGlobalSession); /* Create a global session, but do not set up the core module. The core module can then be loaded via loadCoreModule or compileCoreModule @@ -4247,10 +4375,10 @@ then be loaded via loadCoreModule or compileCoreModule @param apiVersion Pass in SLANG_API_VERSION @param outGlobalSession (out)The created global session that doesn't have a core module setup. -NOTE! API is experimental and not ready for production code +NOTE! API is experimental and not ready for production code */ SLANG_EXTERN_C SLANG_API SlangResult slang_createGlobalSessionWithoutCoreModule( - SlangInt apiVersion, + SlangInt apiVersion, slang::IGlobalSession** outGlobalSession); /* Returns a blob that contains the serialized core module. @@ -4270,13 +4398,15 @@ SLANG_EXTERN_C SLANG_API void slang_shutdown(); namespace slang { - inline SlangResult createGlobalSession( - slang::IGlobalSession** outGlobalSession) - { - return slang_createGlobalSession(SLANG_API_VERSION, outGlobalSession); - } - inline void shutdown() { slang_shutdown(); } +inline SlangResult createGlobalSession(slang::IGlobalSession** outGlobalSession) +{ + return slang_createGlobalSession(SLANG_API_VERSION, outGlobalSession); +} +inline void shutdown() +{ + slang_shutdown(); } +} // namespace slang #endif // C++ helpers diff --git a/prelude/slang-cpp-host-prelude.h b/prelude/slang-cpp-host-prelude.h index 48056169d..8bc0f5cad 100644 --- a/prelude/slang-cpp-host-prelude.h +++ b/prelude/slang-cpp-host-prelude.h @@ -1,8 +1,8 @@ #ifndef SLANG_CPP_HOST_PRELUDE_H #define SLANG_CPP_HOST_PRELUDE_H -#include #include +#include #include #define SLANG_COM_PTR_ENABLE_REF_OPERATOR 1 @@ -14,42 +14,45 @@ #ifdef SLANG_LLVM #include "slang-llvm.h" #else // SLANG_LLVM -# if SLANG_GCC_FAMILY && __GNUC__ < 6 -# include -# define SLANG_PRELUDE_STD std:: -# else -# include -# define SLANG_PRELUDE_STD -# endif - -# include -# include -# include -# include +#if SLANG_GCC_FAMILY && __GNUC__ < 6 +#include +#define SLANG_PRELUDE_STD std:: +#else +#include +#define SLANG_PRELUDE_STD +#endif + +#include +#include +#include +#include #endif // SLANG_LLVM #if defined(_MSC_VER) -# define SLANG_PRELUDE_SHARED_LIB_EXPORT __declspec(dllexport) +#define SLANG_PRELUDE_SHARED_LIB_EXPORT __declspec(dllexport) #else -# define SLANG_PRELUDE_SHARED_LIB_EXPORT __attribute__((__visibility__("default"))) -//# define SLANG_PRELUDE_SHARED_LIB_EXPORT __attribute__ ((dllexport)) __attribute__((__visibility__("default"))) -#endif - -#ifdef __cplusplus -# define SLANG_PRELUDE_EXTERN_C extern "C" -# define SLANG_PRELUDE_EXTERN_C_START extern "C" { -# define SLANG_PRELUDE_EXTERN_C_END } +#define SLANG_PRELUDE_SHARED_LIB_EXPORT __attribute__((__visibility__("default"))) +// # define SLANG_PRELUDE_SHARED_LIB_EXPORT __attribute__ ((dllexport)) +// __attribute__((__visibility__("default"))) +#endif + +#ifdef __cplusplus +#define SLANG_PRELUDE_EXTERN_C extern "C" +#define SLANG_PRELUDE_EXTERN_C_START \ + extern "C" \ + { +#define SLANG_PRELUDE_EXTERN_C_END } #else -# define SLANG_PRELUDE_EXTERN_C -# define SLANG_PRELUDE_EXTERN_C_START -# define SLANG_PRELUDE_EXTERN_C_END -#endif +#define SLANG_PRELUDE_EXTERN_C +#define SLANG_PRELUDE_EXTERN_C_START +#define SLANG_PRELUDE_EXTERN_C_END +#endif #include "slang-cpp-scalar-intrinsics.h" using namespace Slang; template -using Slang_FuncType = TResult(SLANG_MCALL *)(Args...); +using Slang_FuncType = TResult(SLANG_MCALL*)(Args...); #endif diff --git a/prelude/slang-cpp-prelude.h b/prelude/slang-cpp-prelude.h index 2b848dc3b..4dacac9c5 100644 --- a/prelude/slang-cpp-prelude.h +++ b/prelude/slang-cpp-prelude.h @@ -2,42 +2,45 @@ #define SLANG_CPP_PRELUDE_H // Because the signiture of isnan, isfinite, and is isinf changed in C++, we use the macro -// to use the version in the std namespace. +// to use the version in the std namespace. // https://stackoverflow.com/questions/39130040/cmath-hides-isnan-in-math-h-in-c14-c11 - + #ifdef SLANG_LLVM #include "slang-llvm.h" #else // SLANG_LLVM -# if SLANG_GCC_FAMILY && __GNUC__ < 6 -# include -# define SLANG_PRELUDE_STD std:: -# else -# include -# define SLANG_PRELUDE_STD -# endif - -# include -# include -# include -# include +#if SLANG_GCC_FAMILY && __GNUC__ < 6 +#include +#define SLANG_PRELUDE_STD std:: +#else +#include +#define SLANG_PRELUDE_STD +#endif + +#include +#include +#include +#include #endif // SLANG_LLVM #if defined(_MSC_VER) -# define SLANG_PRELUDE_SHARED_LIB_EXPORT __declspec(dllexport) +#define SLANG_PRELUDE_SHARED_LIB_EXPORT __declspec(dllexport) #else -# define SLANG_PRELUDE_SHARED_LIB_EXPORT __attribute__((__visibility__("default"))) -//# define SLANG_PRELUDE_SHARED_LIB_EXPORT __attribute__ ((dllexport)) __attribute__((__visibility__("default"))) -#endif - -#ifdef __cplusplus -# define SLANG_PRELUDE_EXTERN_C extern "C" -# define SLANG_PRELUDE_EXTERN_C_START extern "C" { -# define SLANG_PRELUDE_EXTERN_C_END } +#define SLANG_PRELUDE_SHARED_LIB_EXPORT __attribute__((__visibility__("default"))) +// # define SLANG_PRELUDE_SHARED_LIB_EXPORT __attribute__ ((dllexport)) +// __attribute__((__visibility__("default"))) +#endif + +#ifdef __cplusplus +#define SLANG_PRELUDE_EXTERN_C extern "C" +#define SLANG_PRELUDE_EXTERN_C_START \ + extern "C" \ + { +#define SLANG_PRELUDE_EXTERN_C_END } #else -# define SLANG_PRELUDE_EXTERN_C -# define SLANG_PRELUDE_EXTERN_C_START -# define SLANG_PRELUDE_EXTERN_C_END -#endif +#define SLANG_PRELUDE_EXTERN_C +#define SLANG_PRELUDE_EXTERN_C_START +#define SLANG_PRELUDE_EXTERN_C_END +#endif #define SLANG_PRELUDE_EXPORT SLANG_PRELUDE_EXTERN_C SLANG_PRELUDE_SHARED_LIB_EXPORT #define SLANG_PRELUDE_EXPORT_START SLANG_PRELUDE_EXTERN_C_START SLANG_PRELUDE_SHARED_LIB_EXPORT @@ -45,65 +48,65 @@ #ifndef INFINITY // Must overflow for double -# define INFINITY float(1e+300 * 1e+300) +#define INFINITY float(1e+300 * 1e+300) #endif #ifndef SLANG_INFINITY -# define SLANG_INFINITY INFINITY +#define SLANG_INFINITY INFINITY #endif // Detect the compiler type #ifndef SLANG_COMPILER -# define SLANG_COMPILER +#define SLANG_COMPILER /* Compiler defines, see http://sourceforge.net/p/predef/wiki/Compilers/ NOTE that SLANG_VC holds the compiler version - not just 1 or 0 */ -# if defined(_MSC_VER) -# if _MSC_VER >= 1900 -# define SLANG_VC 14 -# elif _MSC_VER >= 1800 -# define SLANG_VC 12 -# elif _MSC_VER >= 1700 -# define SLANG_VC 11 -# elif _MSC_VER >= 1600 -# define SLANG_VC 10 -# elif _MSC_VER >= 1500 -# define SLANG_VC 9 -# else -# error "unknown version of Visual C++ compiler" -# endif -# elif defined(__clang__) -# define SLANG_CLANG 1 -# elif defined(__SNC__) -# define SLANG_SNC 1 -# elif defined(__ghs__) -# define SLANG_GHS 1 -# elif defined(__GNUC__) /* note: __clang__, __SNC__, or __ghs__ imply __GNUC__ */ -# define SLANG_GCC 1 -# else -# error "unknown compiler" -# endif +#if defined(_MSC_VER) +#if _MSC_VER >= 1900 +#define SLANG_VC 14 +#elif _MSC_VER >= 1800 +#define SLANG_VC 12 +#elif _MSC_VER >= 1700 +#define SLANG_VC 11 +#elif _MSC_VER >= 1600 +#define SLANG_VC 10 +#elif _MSC_VER >= 1500 +#define SLANG_VC 9 +#else +#error "unknown version of Visual C++ compiler" +#endif +#elif defined(__clang__) +#define SLANG_CLANG 1 +#elif defined(__SNC__) +#define SLANG_SNC 1 +#elif defined(__ghs__) +#define SLANG_GHS 1 +#elif defined(__GNUC__) /* note: __clang__, __SNC__, or __ghs__ imply __GNUC__ */ +#define SLANG_GCC 1 +#else +#error "unknown compiler" +#endif /* Any compilers not detected by the above logic are now now explicitly zeroed out. */ -# ifndef SLANG_VC -# define SLANG_VC 0 -# endif -# ifndef SLANG_CLANG -# define SLANG_CLANG 0 -# endif -# ifndef SLANG_SNC -# define SLANG_SNC 0 -# endif -# ifndef SLANG_GHS -# define SLANG_GHS 0 -# endif -# ifndef SLANG_GCC -# define SLANG_GCC 0 -# endif +#ifndef SLANG_VC +#define SLANG_VC 0 +#endif +#ifndef SLANG_CLANG +#define SLANG_CLANG 0 +#endif +#ifndef SLANG_SNC +#define SLANG_SNC 0 +#endif +#ifndef SLANG_GHS +#define SLANG_GHS 0 +#endif +#ifndef SLANG_GCC +#define SLANG_GCC 0 +#endif #endif /* SLANG_COMPILER */ /* @@ -116,89 +119,90 @@ used later in the file. Most applications should not need to touch this section. */ #ifndef SLANG_PLATFORM -# define SLANG_PLATFORM +#define SLANG_PLATFORM /** Operating system defines, see http://sourceforge.net/p/predef/wiki/OperatingSystems/ */ -# if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_PARTITION_APP -# define SLANG_WINRT 1 /* Windows Runtime, either on Windows RT or Windows 8 */ -# elif defined(XBOXONE) -# define SLANG_XBOXONE 1 -# elif defined(_WIN64) /* note: XBOXONE implies _WIN64 */ -# define SLANG_WIN64 1 -# elif defined(_M_PPC) -# define SLANG_X360 1 -# elif defined(_WIN32) /* note: _M_PPC implies _WIN32 */ -# define SLANG_WIN32 1 -# elif defined(__ANDROID__) -# define SLANG_ANDROID 1 -# elif defined(__linux__) || defined(__CYGWIN__) /* note: __ANDROID__ implies __linux__ */ -# define SLANG_LINUX 1 -# elif defined(__APPLE__) && !defined(SLANG_LLVM) -# include "TargetConditionals.h" -# if TARGET_OS_MAC -# define SLANG_OSX 1 -# else -# define SLANG_IOS 1 -# endif -# elif defined(__APPLE__) -// On `slang-llvm` we can't inclue "TargetConditionals.h" in general, so for now assume its OSX. -# define SLANG_OSX 1 -# elif defined(__CELLOS_LV2__) -# define SLANG_PS3 1 -# elif defined(__ORBIS__) -# define SLANG_PS4 1 -# elif defined(__SNC__) && defined(__arm__) -# define SLANG_PSP2 1 -# elif defined(__ghs__) -# define SLANG_WIIU 1 -# else -# error "unknown target platform" -# endif +#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_PARTITION_APP +#define SLANG_WINRT 1 /* Windows Runtime, either on Windows RT or Windows 8 */ +#elif defined(XBOXONE) +#define SLANG_XBOXONE 1 +#elif defined(_WIN64) /* note: XBOXONE implies _WIN64 */ +#define SLANG_WIN64 1 +#elif defined(_M_PPC) +#define SLANG_X360 1 +#elif defined(_WIN32) /* note: _M_PPC implies _WIN32 */ +#define SLANG_WIN32 1 +#elif defined(__ANDROID__) +#define SLANG_ANDROID 1 +#elif defined(__linux__) || defined(__CYGWIN__) /* note: __ANDROID__ implies __linux__ */ +#define SLANG_LINUX 1 +#elif defined(__APPLE__) && !defined(SLANG_LLVM) +#include "TargetConditionals.h" +#if TARGET_OS_MAC +#define SLANG_OSX 1 +#else +#define SLANG_IOS 1 +#endif +#elif defined(__APPLE__) +// On `slang-llvm` we can't inclue "TargetConditionals.h" in general, so for now assume its +// OSX. +#define SLANG_OSX 1 +#elif defined(__CELLOS_LV2__) +#define SLANG_PS3 1 +#elif defined(__ORBIS__) +#define SLANG_PS4 1 +#elif defined(__SNC__) && defined(__arm__) +#define SLANG_PSP2 1 +#elif defined(__ghs__) +#define SLANG_WIIU 1 +#else +#error "unknown target platform" +#endif /* Any platforms not detected by the above logic are now now explicitly zeroed out. */ -# ifndef SLANG_WINRT -# define SLANG_WINRT 0 -# endif -# ifndef SLANG_XBOXONE -# define SLANG_XBOXONE 0 -# endif -# ifndef SLANG_WIN64 -# define SLANG_WIN64 0 -# endif -# ifndef SLANG_X360 -# define SLANG_X360 0 -# endif -# ifndef SLANG_WIN32 -# define SLANG_WIN32 0 -# endif -# ifndef SLANG_ANDROID -# define SLANG_ANDROID 0 -# endif -# ifndef SLANG_LINUX -# define SLANG_LINUX 0 -# endif -# ifndef SLANG_IOS -# define SLANG_IOS 0 -# endif -# ifndef SLANG_OSX -# define SLANG_OSX 0 -# endif -# ifndef SLANG_PS3 -# define SLANG_PS3 0 -# endif -# ifndef SLANG_PS4 -# define SLANG_PS4 0 -# endif -# ifndef SLANG_PSP2 -# define SLANG_PSP2 0 -# endif -# ifndef SLANG_WIIU -# define SLANG_WIIU 0 -# endif +#ifndef SLANG_WINRT +#define SLANG_WINRT 0 +#endif +#ifndef SLANG_XBOXONE +#define SLANG_XBOXONE 0 +#endif +#ifndef SLANG_WIN64 +#define SLANG_WIN64 0 +#endif +#ifndef SLANG_X360 +#define SLANG_X360 0 +#endif +#ifndef SLANG_WIN32 +#define SLANG_WIN32 0 +#endif +#ifndef SLANG_ANDROID +#define SLANG_ANDROID 0 +#endif +#ifndef SLANG_LINUX +#define SLANG_LINUX 0 +#endif +#ifndef SLANG_IOS +#define SLANG_IOS 0 +#endif +#ifndef SLANG_OSX +#define SLANG_OSX 0 +#endif +#ifndef SLANG_PS3 +#define SLANG_PS3 0 +#endif +#ifndef SLANG_PS4 +#define SLANG_PS4 0 +#endif +#ifndef SLANG_PSP2 +#define SLANG_PSP2 0 +#endif +#ifndef SLANG_WIIU +#define SLANG_WIIU 0 +#endif #endif /* SLANG_PLATFORM */ /* Shorthands for "families" of compilers/platforms */ @@ -206,37 +210,38 @@ Any platforms not detected by the above logic are now now explicitly zeroed out. #define SLANG_WINDOWS_FAMILY (SLANG_WINRT || SLANG_WIN32 || SLANG_WIN64) #define SLANG_MICROSOFT_FAMILY (SLANG_XBOXONE || SLANG_X360 || SLANG_WINDOWS_FAMILY) #define SLANG_LINUX_FAMILY (SLANG_LINUX || SLANG_ANDROID) -#define SLANG_APPLE_FAMILY (SLANG_IOS || SLANG_OSX) /* equivalent to #if __APPLE__ */ -#define SLANG_UNIX_FAMILY (SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY) /* shortcut for unix/posix platforms */ +#define SLANG_APPLE_FAMILY (SLANG_IOS || SLANG_OSX) /* equivalent to #if __APPLE__ */ +#define SLANG_UNIX_FAMILY \ + (SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY) /* shortcut for unix/posix platforms */ // GCC Specific #if SLANG_GCC_FAMILY -# define SLANG_ALIGN_OF(T) __alignof__(T) +#define SLANG_ALIGN_OF(T) __alignof__(T) -# define SLANG_BREAKPOINT(id) __builtin_trap() +#define SLANG_BREAKPOINT(id) __builtin_trap() -// Use this macro instead of offsetof, because gcc produces warning if offsetof is used on a +// Use this macro instead of offsetof, because gcc produces warning if offsetof is used on a // non POD type, even though it produces the correct result -# define SLANG_OFFSET_OF(T, ELEMENT) (size_t(&((T*)1)->ELEMENT) - 1) +#define SLANG_OFFSET_OF(T, ELEMENT) (size_t(&((T*)1)->ELEMENT) - 1) #endif // SLANG_GCC_FAMILY // Microsoft VC specific #if SLANG_VC -# define SLANG_ALIGN_OF(T) __alignof(T) +#define SLANG_ALIGN_OF(T) __alignof(T) -# define SLANG_BREAKPOINT(id) __debugbreak(); +#define SLANG_BREAKPOINT(id) __debugbreak(); #endif // SLANG_VC // Default impls #ifndef SLANG_OFFSET_OF -# define SLANG_OFFSET_OF(X, Y) offsetof(X, Y) +#define SLANG_OFFSET_OF(X, Y) offsetof(X, Y) #endif #ifndef SLANG_BREAKPOINT // Make it crash with a write to 0! -# define SLANG_BREAKPOINT(id) (*((int*)0) = int(id)); +#define SLANG_BREAKPOINT(id) (*((int*)0) = int(id)); #endif // If slang.h has been included we don't need any of these definitions @@ -244,33 +249,33 @@ Any platforms not detected by the above logic are now now explicitly zeroed out. /* Macro for declaring if a method is no throw. Should be set before the return parameter. */ #ifndef SLANG_NO_THROW -# if SLANG_WINDOWS_FAMILY && !defined(SLANG_DISABLE_EXCEPTIONS) -# define SLANG_NO_THROW __declspec(nothrow) -# endif +#if SLANG_WINDOWS_FAMILY && !defined(SLANG_DISABLE_EXCEPTIONS) +#define SLANG_NO_THROW __declspec(nothrow) +#endif #endif #ifndef SLANG_NO_THROW -# define SLANG_NO_THROW +#define SLANG_NO_THROW #endif /* The `SLANG_STDCALL` and `SLANG_MCALL` defines are used to set the calling convention for interface methods. */ #ifndef SLANG_STDCALL -# if SLANG_MICROSOFT_FAMILY -# define SLANG_STDCALL __stdcall -# else -# define SLANG_STDCALL -# endif +#if SLANG_MICROSOFT_FAMILY +#define SLANG_STDCALL __stdcall +#else +#define SLANG_STDCALL +#endif #endif #ifndef SLANG_MCALL -# define SLANG_MCALL SLANG_STDCALL +#define SLANG_MCALL SLANG_STDCALL #endif #ifndef SLANG_FORCE_INLINE -# define SLANG_FORCE_INLINE inline +#define SLANG_FORCE_INLINE inline #endif -// TODO(JS): Should these be in slang-cpp-types.h? +// TODO(JS): Should these be in slang-cpp-types.h? // They are more likely to clash with slang.h struct SlangUUID @@ -278,24 +283,25 @@ struct SlangUUID uint32_t data1; uint16_t data2; uint16_t data3; - uint8_t data4[8]; + uint8_t data4[8]; }; typedef int32_t SlangResult; struct ISlangUnknown { - virtual SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) = 0; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + queryInterface(SlangUUID const& uuid, void** outObject) = 0; virtual SLANG_NO_THROW uint32_t SLANG_MCALL addRef() = 0; virtual SLANG_NO_THROW uint32_t SLANG_MCALL release() = 0; }; -#define SLANG_COM_INTERFACE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ - public: \ - SLANG_FORCE_INLINE static const SlangUUID& getTypeGuid() \ - { \ - static const SlangUUID guid = { a, b, c, d0, d1, d2, d3, d4, d5, d6, d7 }; \ - return guid; \ +#define SLANG_COM_INTERFACE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ +public: \ + SLANG_FORCE_INLINE static const SlangUUID& getTypeGuid() \ + { \ + static const SlangUUID guid = {a, b, c, d0, d1, d2, d3, d4, d5, d6, d7}; \ + return guid; \ } #endif // SLANG_H @@ -304,13 +310,13 @@ struct ISlangUnknown #include "slang-cpp-scalar-intrinsics.h" #include "slang-cpp-types.h" -// TODO(JS): Hack! Output C++ code from slang can copy uninitialized variables. +// TODO(JS): Hack! Output C++ code from slang can copy uninitialized variables. #if defined(_MSC_VER) -# pragma warning(disable : 4700) +#pragma warning(disable : 4700) #endif #ifndef SLANG_UNROLL -# define SLANG_UNROLL +#define SLANG_UNROLL #endif #endif diff --git a/prelude/slang-cpp-scalar-intrinsics.h b/prelude/slang-cpp-scalar-intrinsics.h index 1ade8614f..6aa72df4f 100644 --- a/prelude/slang-cpp-scalar-intrinsics.h +++ b/prelude/slang-cpp-scalar-intrinsics.h @@ -2,24 +2,26 @@ #define SLANG_PRELUDE_SCALAR_INTRINSICS_H #if !defined(SLANG_LLVM) && SLANG_PROCESSOR_X86_64 && SLANG_VC -// If we have visual studio and 64 bit processor, we can assume we have popcnt, and can include x86 intrinsics -# include +// If we have visual studio and 64 bit processor, we can assume we have popcnt, and can include +// x86 intrinsics +#include #endif #ifndef SLANG_FORCE_INLINE -# define SLANG_FORCE_INLINE inline +#define SLANG_FORCE_INLINE inline #endif #ifdef SLANG_PRELUDE_NAMESPACE -namespace SLANG_PRELUDE_NAMESPACE { +namespace SLANG_PRELUDE_NAMESPACE +{ #endif #ifndef SLANG_PRELUDE_PI -# define SLANG_PRELUDE_PI 3.14159265358979323846 +#define SLANG_PRELUDE_PI 3.14159265358979323846 #endif -union Union32 +union Union32 { uint32_t u; int32_t i; @@ -34,10 +36,30 @@ union Union64 }; // 32 bit cast conversions -SLANG_FORCE_INLINE int32_t _bitCastFloatToInt(float f) { Union32 u; u.f = f; return u.i; } -SLANG_FORCE_INLINE float _bitCastIntToFloat(int32_t i) { Union32 u; u.i = i; return u.f; } -SLANG_FORCE_INLINE uint32_t _bitCastFloatToUInt(float f) { Union32 u; u.f = f; return u.u; } -SLANG_FORCE_INLINE float _bitCastUIntToFloat(uint32_t ui) { Union32 u; u.u = ui; return u.f; } +SLANG_FORCE_INLINE int32_t _bitCastFloatToInt(float f) +{ + Union32 u; + u.f = f; + return u.i; +} +SLANG_FORCE_INLINE float _bitCastIntToFloat(int32_t i) +{ + Union32 u; + u.i = i; + return u.f; +} +SLANG_FORCE_INLINE uint32_t _bitCastFloatToUInt(float f) +{ + Union32 u; + u.f = f; + return u.u; +} +SLANG_FORCE_INLINE float _bitCastUIntToFloat(uint32_t ui) +{ + Union32 u; + u.u = ui; + return u.f; +} // ----------------------------- F16 ----------------------------------------- @@ -61,27 +83,27 @@ SLANG_FORCE_INLINE uint32_t f32tof16(const float value) if (e == 0xff) { // Could be a NAN or INF. Is INF if *input* mantissa is 0. - + // Remove last bit for rounding to make output mantissa. m >>= 1; - + // We *assume* float16/float32 signaling bit and remaining bits // semantics are the same. (The signalling bit convention is target specific!). // Non signal bit's usage within mantissa for a NAN are also target specific. - - // If the m is 0, it could be because the result is INF, but it could also be because all the - // bits that made NAN were dropped as we have less mantissa bits in f16. - + + // If the m is 0, it could be because the result is INF, but it could also be because all + // the bits that made NAN were dropped as we have less mantissa bits in f16. + // To fix for this we make non zero if m is 0 and the input mantissa was not. // This will (typically) produce a signalling NAN. m += uint32_t(m == 0 && (inBits & 0x007fffffu)); - + // Combine for output return (bits | 0x7c00u | m); } if (e > 142) { - // INF. + // INF. return bits | 0x7c00u; } if (e < 113) @@ -105,7 +127,7 @@ SLANG_FORCE_INLINE float f16tof32(const uint32_t value) if (exponent == 0) { - // If mantissa is 0 we are done, as output is 0. + // If mantissa is 0 we are done, as output is 0. // If it's not zero we must have a denormal. if (mantissa) { @@ -113,16 +135,17 @@ SLANG_FORCE_INLINE float f16tof32(const uint32_t value) return _bitCastIntToFloat(sign | ((value & 0x7fff) << 13)) * g_f16tof32Magic; } } - else + else { - // If the exponent is NAN or INF exponent is 0x1f on input. + // If the exponent is NAN or INF exponent is 0x1f on input. // If that's the case, we just need to set the exponent to 0xff on output - // and the mantissa can just stay the same. If its 0 it's INF, else it is NAN and we just copy the bits + // and the mantissa can just stay the same. If its 0 it's INF, else it is NAN and we just + // copy the bits // // Else we need to correct the exponent in the normalized case. exponent = (exponent == 0x1F) ? 0xff : (exponent + (-15 + 127)); } - + return _bitCastUIntToFloat(sign | (exponent << 23) | (mantissa << 13)); } @@ -135,7 +158,7 @@ SLANG_FORCE_INLINE float F32_calcSafeRadians(float radians); SLANG_PRELUDE_EXTERN_C_START -// Unary +// Unary float F32_ceil(float f); float F32_floor(float f); float F32_round(float f); @@ -158,12 +181,18 @@ float F32_trunc(float f); float F32_sqrt(float f); bool F32_isnan(float f); -bool F32_isfinite(float f); +bool F32_isfinite(float f); bool F32_isinf(float f); // Binary -SLANG_FORCE_INLINE float F32_min(float a, float b) { return a < b ? a : b; } -SLANG_FORCE_INLINE float F32_max(float a, float b) { return a > b ? a : b; } +SLANG_FORCE_INLINE float F32_min(float a, float b) +{ + return a < b ? a : b; +} +SLANG_FORCE_INLINE float F32_max(float a, float b) +{ + return a > b ? a : b; +} float F32_pow(float a, float b); float F32_fmod(float a, float b); float F32_remainder(float a, float b); @@ -174,47 +203,140 @@ float F32_frexp(float x, int* e); float F32_modf(float x, float* ip); // Ternary -SLANG_FORCE_INLINE float F32_fma(float a, float b, float c) { return a * b + c; } +SLANG_FORCE_INLINE float F32_fma(float a, float b, float c) +{ + return a * b + c; +} SLANG_PRELUDE_EXTERN_C_END #else -// Unary -SLANG_FORCE_INLINE float F32_ceil(float f) { return ::ceilf(f); } -SLANG_FORCE_INLINE float F32_floor(float f) { return ::floorf(f); } -SLANG_FORCE_INLINE float F32_round(float f) { return ::roundf(f); } -SLANG_FORCE_INLINE float F32_sin(float f) { return ::sinf(f); } -SLANG_FORCE_INLINE float F32_cos(float f) { return ::cosf(f); } -SLANG_FORCE_INLINE float F32_tan(float f) { return ::tanf(f); } -SLANG_FORCE_INLINE float F32_asin(float f) { return ::asinf(f); } -SLANG_FORCE_INLINE float F32_acos(float f) { return ::acosf(f); } -SLANG_FORCE_INLINE float F32_atan(float f) { return ::atanf(f); } -SLANG_FORCE_INLINE float F32_sinh(float f) { return ::sinhf(f); } -SLANG_FORCE_INLINE float F32_cosh(float f) { return ::coshf(f); } -SLANG_FORCE_INLINE float F32_tanh(float f) { return ::tanhf(f); } -SLANG_FORCE_INLINE float F32_log2(float f) { return ::log2f(f); } -SLANG_FORCE_INLINE float F32_log(float f) { return ::logf(f); } -SLANG_FORCE_INLINE float F32_log10(float f) { return ::log10f(f); } -SLANG_FORCE_INLINE float F32_exp2(float f) { return ::exp2f(f); } -SLANG_FORCE_INLINE float F32_exp(float f) { return ::expf(f); } -SLANG_FORCE_INLINE float F32_abs(float f) { return ::fabsf(f); } -SLANG_FORCE_INLINE float F32_trunc(float f) { return ::truncf(f); } -SLANG_FORCE_INLINE float F32_sqrt(float f) { return ::sqrtf(f); } - -SLANG_FORCE_INLINE bool F32_isnan(float f) { return SLANG_PRELUDE_STD isnan(f); } -SLANG_FORCE_INLINE bool F32_isfinite(float f) { return SLANG_PRELUDE_STD isfinite(f); } -SLANG_FORCE_INLINE bool F32_isinf(float f) { return SLANG_PRELUDE_STD isinf(f); } +// Unary +SLANG_FORCE_INLINE float F32_ceil(float f) +{ + return ::ceilf(f); +} +SLANG_FORCE_INLINE float F32_floor(float f) +{ + return ::floorf(f); +} +SLANG_FORCE_INLINE float F32_round(float f) +{ + return ::roundf(f); +} +SLANG_FORCE_INLINE float F32_sin(float f) +{ + return ::sinf(f); +} +SLANG_FORCE_INLINE float F32_cos(float f) +{ + return ::cosf(f); +} +SLANG_FORCE_INLINE float F32_tan(float f) +{ + return ::tanf(f); +} +SLANG_FORCE_INLINE float F32_asin(float f) +{ + return ::asinf(f); +} +SLANG_FORCE_INLINE float F32_acos(float f) +{ + return ::acosf(f); +} +SLANG_FORCE_INLINE float F32_atan(float f) +{ + return ::atanf(f); +} +SLANG_FORCE_INLINE float F32_sinh(float f) +{ + return ::sinhf(f); +} +SLANG_FORCE_INLINE float F32_cosh(float f) +{ + return ::coshf(f); +} +SLANG_FORCE_INLINE float F32_tanh(float f) +{ + return ::tanhf(f); +} +SLANG_FORCE_INLINE float F32_log2(float f) +{ + return ::log2f(f); +} +SLANG_FORCE_INLINE float F32_log(float f) +{ + return ::logf(f); +} +SLANG_FORCE_INLINE float F32_log10(float f) +{ + return ::log10f(f); +} +SLANG_FORCE_INLINE float F32_exp2(float f) +{ + return ::exp2f(f); +} +SLANG_FORCE_INLINE float F32_exp(float f) +{ + return ::expf(f); +} +SLANG_FORCE_INLINE float F32_abs(float f) +{ + return ::fabsf(f); +} +SLANG_FORCE_INLINE float F32_trunc(float f) +{ + return ::truncf(f); +} +SLANG_FORCE_INLINE float F32_sqrt(float f) +{ + return ::sqrtf(f); +} + +SLANG_FORCE_INLINE bool F32_isnan(float f) +{ + return SLANG_PRELUDE_STD isnan(f); +} +SLANG_FORCE_INLINE bool F32_isfinite(float f) +{ + return SLANG_PRELUDE_STD isfinite(f); +} +SLANG_FORCE_INLINE bool F32_isinf(float f) +{ + return SLANG_PRELUDE_STD isinf(f); +} // Binary -SLANG_FORCE_INLINE float F32_min(float a, float b) { return ::fminf(a, b); } -SLANG_FORCE_INLINE float F32_max(float a, float b) { return ::fmaxf(a, b); } -SLANG_FORCE_INLINE float F32_pow(float a, float b) { return ::powf(a, b); } -SLANG_FORCE_INLINE float F32_fmod(float a, float b) { return ::fmodf(a, b); } -SLANG_FORCE_INLINE float F32_remainder(float a, float b) { return ::remainderf(a, b); } -SLANG_FORCE_INLINE float F32_atan2(float a, float b) { return float(::atan2(a, b)); } +SLANG_FORCE_INLINE float F32_min(float a, float b) +{ + return ::fminf(a, b); +} +SLANG_FORCE_INLINE float F32_max(float a, float b) +{ + return ::fmaxf(a, b); +} +SLANG_FORCE_INLINE float F32_pow(float a, float b) +{ + return ::powf(a, b); +} +SLANG_FORCE_INLINE float F32_fmod(float a, float b) +{ + return ::fmodf(a, b); +} +SLANG_FORCE_INLINE float F32_remainder(float a, float b) +{ + return ::remainderf(a, b); +} +SLANG_FORCE_INLINE float F32_atan2(float a, float b) +{ + return float(::atan2(a, b)); +} -SLANG_FORCE_INLINE float F32_frexp(float x, int* e) { return ::frexpf(x, e); } +SLANG_FORCE_INLINE float F32_frexp(float x, int* e) +{ + return ::frexpf(x, e); +} SLANG_FORCE_INLINE float F32_modf(float x, float* ip) { @@ -222,26 +344,48 @@ SLANG_FORCE_INLINE float F32_modf(float x, float* ip) } // Ternary -SLANG_FORCE_INLINE float F32_fma(float a, float b, float c) { return ::fmaf(a, b, c); } +SLANG_FORCE_INLINE float F32_fma(float a, float b, float c) +{ + return ::fmaf(a, b, c); +} #endif SLANG_FORCE_INLINE float F32_calcSafeRadians(float radians) { - // Put 0 to 2pi cycles to cycle around 0 to 1 - float a = radians * (1.0f / float(SLANG_PRELUDE_PI * 2)); + // Put 0 to 2pi cycles to cycle around 0 to 1 + float a = radians * (1.0f / float(SLANG_PRELUDE_PI * 2)); // Get truncated fraction, as value in 0 - 1 range a = a - F32_floor(a); // Convert back to 0 - 2pi range - return (a * float(SLANG_PRELUDE_PI * 2)); + return (a * float(SLANG_PRELUDE_PI * 2)); } -SLANG_FORCE_INLINE float F32_rsqrt(float f) { return 1.0f / F32_sqrt(f); } -SLANG_FORCE_INLINE float F32_sign(float f) { return ( f == 0.0f) ? f : (( f < 0.0f) ? -1.0f : 1.0f); } -SLANG_FORCE_INLINE float F32_frac(float f) { return f - F32_floor(f); } +SLANG_FORCE_INLINE float F32_rsqrt(float f) +{ + return 1.0f / F32_sqrt(f); +} +SLANG_FORCE_INLINE float F32_sign(float f) +{ + return (f == 0.0f) ? f : ((f < 0.0f) ? -1.0f : 1.0f); +} +SLANG_FORCE_INLINE float F32_frac(float f) +{ + return f - F32_floor(f); +} -SLANG_FORCE_INLINE uint32_t F32_asuint(float f) { Union32 u; u.f = f; return u.u; } -SLANG_FORCE_INLINE int32_t F32_asint(float f) { Union32 u; u.f = f; return u.i; } +SLANG_FORCE_INLINE uint32_t F32_asuint(float f) +{ + Union32 u; + u.f = f; + return u.u; +} +SLANG_FORCE_INLINE int32_t F32_asint(float f) +{ + Union32 u; + u.f = f; + return u.i; +} // ----------------------------- F64 ----------------------------------------- @@ -251,7 +395,7 @@ SLANG_FORCE_INLINE double F64_calcSafeRadians(double radians); SLANG_PRELUDE_EXTERN_C_START -// Unary +// Unary double F64_ceil(double f); double F64_floor(double f); double F64_round(double f); @@ -278,8 +422,14 @@ bool F64_isfinite(double f); bool F64_isinf(double f); // Binary -SLANG_FORCE_INLINE double F64_min(double a, double b) { return a < b ? a : b; } -SLANG_FORCE_INLINE double F64_max(double a, double b) { return a > b ? a : b; } +SLANG_FORCE_INLINE double F64_min(double a, double b) +{ + return a < b ? a : b; +} +SLANG_FORCE_INLINE double F64_max(double a, double b) +{ + return a > b ? a : b; +} double F64_pow(double a, double b); double F64_fmod(double a, double b); double F64_remainder(double a, double b); @@ -290,48 +440,141 @@ double F64_frexp(double x, int* e); double F64_modf(double x, double* ip); // Ternary -SLANG_FORCE_INLINE double F64_fma(double a, double b, double c) { return a * b + c; } +SLANG_FORCE_INLINE double F64_fma(double a, double b, double c) +{ + return a * b + c; +} SLANG_PRELUDE_EXTERN_C_END #else // SLANG_LLVM -// Unary -SLANG_FORCE_INLINE double F64_ceil(double f) { return ::ceil(f); } -SLANG_FORCE_INLINE double F64_floor(double f) { return ::floor(f); } -SLANG_FORCE_INLINE double F64_round(double f) { return ::round(f); } -SLANG_FORCE_INLINE double F64_sin(double f) { return ::sin(f); } -SLANG_FORCE_INLINE double F64_cos(double f) { return ::cos(f); } -SLANG_FORCE_INLINE double F64_tan(double f) { return ::tan(f); } -SLANG_FORCE_INLINE double F64_asin(double f) { return ::asin(f); } -SLANG_FORCE_INLINE double F64_acos(double f) { return ::acos(f); } -SLANG_FORCE_INLINE double F64_atan(double f) { return ::atan(f); } -SLANG_FORCE_INLINE double F64_sinh(double f) { return ::sinh(f); } -SLANG_FORCE_INLINE double F64_cosh(double f) { return ::cosh(f); } -SLANG_FORCE_INLINE double F64_tanh(double f) { return ::tanh(f); } -SLANG_FORCE_INLINE double F64_log2(double f) { return ::log2(f); } -SLANG_FORCE_INLINE double F64_log(double f) { return ::log(f); } -SLANG_FORCE_INLINE double F64_log10(float f) { return ::log10(f); } -SLANG_FORCE_INLINE double F64_exp2(double f) { return ::exp2(f); } -SLANG_FORCE_INLINE double F64_exp(double f) { return ::exp(f); } -SLANG_FORCE_INLINE double F64_abs(double f) { return ::fabs(f); } -SLANG_FORCE_INLINE double F64_trunc(double f) { return ::trunc(f); } -SLANG_FORCE_INLINE double F64_sqrt(double f) { return ::sqrt(f); } - - -SLANG_FORCE_INLINE bool F64_isnan(double f) { return SLANG_PRELUDE_STD isnan(f); } -SLANG_FORCE_INLINE bool F64_isfinite(double f) { return SLANG_PRELUDE_STD isfinite(f); } -SLANG_FORCE_INLINE bool F64_isinf(double f) { return SLANG_PRELUDE_STD isinf(f); } +// Unary +SLANG_FORCE_INLINE double F64_ceil(double f) +{ + return ::ceil(f); +} +SLANG_FORCE_INLINE double F64_floor(double f) +{ + return ::floor(f); +} +SLANG_FORCE_INLINE double F64_round(double f) +{ + return ::round(f); +} +SLANG_FORCE_INLINE double F64_sin(double f) +{ + return ::sin(f); +} +SLANG_FORCE_INLINE double F64_cos(double f) +{ + return ::cos(f); +} +SLANG_FORCE_INLINE double F64_tan(double f) +{ + return ::tan(f); +} +SLANG_FORCE_INLINE double F64_asin(double f) +{ + return ::asin(f); +} +SLANG_FORCE_INLINE double F64_acos(double f) +{ + return ::acos(f); +} +SLANG_FORCE_INLINE double F64_atan(double f) +{ + return ::atan(f); +} +SLANG_FORCE_INLINE double F64_sinh(double f) +{ + return ::sinh(f); +} +SLANG_FORCE_INLINE double F64_cosh(double f) +{ + return ::cosh(f); +} +SLANG_FORCE_INLINE double F64_tanh(double f) +{ + return ::tanh(f); +} +SLANG_FORCE_INLINE double F64_log2(double f) +{ + return ::log2(f); +} +SLANG_FORCE_INLINE double F64_log(double f) +{ + return ::log(f); +} +SLANG_FORCE_INLINE double F64_log10(float f) +{ + return ::log10(f); +} +SLANG_FORCE_INLINE double F64_exp2(double f) +{ + return ::exp2(f); +} +SLANG_FORCE_INLINE double F64_exp(double f) +{ + return ::exp(f); +} +SLANG_FORCE_INLINE double F64_abs(double f) +{ + return ::fabs(f); +} +SLANG_FORCE_INLINE double F64_trunc(double f) +{ + return ::trunc(f); +} +SLANG_FORCE_INLINE double F64_sqrt(double f) +{ + return ::sqrt(f); +} + + +SLANG_FORCE_INLINE bool F64_isnan(double f) +{ + return SLANG_PRELUDE_STD isnan(f); +} +SLANG_FORCE_INLINE bool F64_isfinite(double f) +{ + return SLANG_PRELUDE_STD isfinite(f); +} +SLANG_FORCE_INLINE bool F64_isinf(double f) +{ + return SLANG_PRELUDE_STD isinf(f); +} // Binary -SLANG_FORCE_INLINE double F64_min(double a, double b) { return ::fmin(a, b); } -SLANG_FORCE_INLINE double F64_max(double a, double b) { return ::fmax(a, b); } -SLANG_FORCE_INLINE double F64_pow(double a, double b) { return ::pow(a, b); } -SLANG_FORCE_INLINE double F64_fmod(double a, double b) { return ::fmod(a, b); } -SLANG_FORCE_INLINE double F64_remainder(double a, double b) { return ::remainder(a, b); } -SLANG_FORCE_INLINE double F64_atan2(double a, double b) { return ::atan2(a, b); } +SLANG_FORCE_INLINE double F64_min(double a, double b) +{ + return ::fmin(a, b); +} +SLANG_FORCE_INLINE double F64_max(double a, double b) +{ + return ::fmax(a, b); +} +SLANG_FORCE_INLINE double F64_pow(double a, double b) +{ + return ::pow(a, b); +} +SLANG_FORCE_INLINE double F64_fmod(double a, double b) +{ + return ::fmod(a, b); +} +SLANG_FORCE_INLINE double F64_remainder(double a, double b) +{ + return ::remainder(a, b); +} +SLANG_FORCE_INLINE double F64_atan2(double a, double b) +{ + return ::atan2(a, b); +} -SLANG_FORCE_INLINE double F64_frexp(double x, int* e) { return ::frexp(x, e); } +SLANG_FORCE_INLINE double F64_frexp(double x, int* e) +{ + return ::frexp(x, e); +} SLANG_FORCE_INLINE double F64_modf(double x, double* ip) { @@ -339,13 +582,25 @@ SLANG_FORCE_INLINE double F64_modf(double x, double* ip) } // Ternary -SLANG_FORCE_INLINE double F64_fma(double a, double b, double c) { return ::fma(a, b, c); } +SLANG_FORCE_INLINE double F64_fma(double a, double b, double c) +{ + return ::fma(a, b, c); +} #endif // SLANG_LLVM -SLANG_FORCE_INLINE double F64_rsqrt(double f) { return 1.0 / F64_sqrt(f); } -SLANG_FORCE_INLINE double F64_sign(double f) { return (f == 0.0) ? f : ((f < 0.0) ? -1.0 : 1.0); } -SLANG_FORCE_INLINE double F64_frac(double f) { return f - F64_floor(f); } +SLANG_FORCE_INLINE double F64_rsqrt(double f) +{ + return 1.0 / F64_sqrt(f); +} +SLANG_FORCE_INLINE double F64_sign(double f) +{ + return (f == 0.0) ? f : ((f < 0.0) ? -1.0 : 1.0); +} +SLANG_FORCE_INLINE double F64_frac(double f) +{ + return f - F64_floor(f); +} SLANG_FORCE_INLINE void F64_asuint(double d, uint32_t* low, uint32_t* hi) { @@ -365,24 +620,41 @@ SLANG_FORCE_INLINE void F64_asint(double d, int32_t* low, int32_t* hi) SLANG_FORCE_INLINE double F64_calcSafeRadians(double radians) { - // Put 0 to 2pi cycles to cycle around 0 to 1 - double a = radians * (1.0f / (SLANG_PRELUDE_PI * 2)); + // Put 0 to 2pi cycles to cycle around 0 to 1 + double a = radians * (1.0f / (SLANG_PRELUDE_PI * 2)); // Get truncated fraction, as value in 0 - 1 range a = a - F64_floor(a); // Convert back to 0 - 2pi range - return (a * (SLANG_PRELUDE_PI * 2)); + return (a * (SLANG_PRELUDE_PI * 2)); } // ----------------------------- I32 ----------------------------------------- -SLANG_FORCE_INLINE int32_t I32_abs(int32_t f) { return (f < 0) ? -f : f; } +SLANG_FORCE_INLINE int32_t I32_abs(int32_t f) +{ + return (f < 0) ? -f : f; +} -SLANG_FORCE_INLINE int32_t I32_min(int32_t a, int32_t b) { return a < b ? a : b; } -SLANG_FORCE_INLINE int32_t I32_max(int32_t a, int32_t b) { return a > b ? a : b; } +SLANG_FORCE_INLINE int32_t I32_min(int32_t a, int32_t b) +{ + return a < b ? a : b; +} +SLANG_FORCE_INLINE int32_t I32_max(int32_t a, int32_t b) +{ + return a > b ? a : b; +} -SLANG_FORCE_INLINE float I32_asfloat(int32_t x) { Union32 u; u.i = x; return u.f; } -SLANG_FORCE_INLINE uint32_t I32_asuint(int32_t x) { return uint32_t(x); } -SLANG_FORCE_INLINE double I32_asdouble(int32_t low, int32_t hi ) +SLANG_FORCE_INLINE float I32_asfloat(int32_t x) +{ + Union32 u; + u.i = x; + return u.f; +} +SLANG_FORCE_INLINE uint32_t I32_asuint(int32_t x) +{ + return uint32_t(x); +} +SLANG_FORCE_INLINE double I32_asdouble(int32_t low, int32_t hi) { Union64 u; u.u = (uint64_t(hi) << 32) | uint32_t(low); @@ -391,13 +663,30 @@ SLANG_FORCE_INLINE double I32_asdouble(int32_t low, int32_t hi ) // ----------------------------- U32 ----------------------------------------- -SLANG_FORCE_INLINE uint32_t U32_abs(uint32_t f) { return f; } +SLANG_FORCE_INLINE uint32_t U32_abs(uint32_t f) +{ + return f; +} -SLANG_FORCE_INLINE uint32_t U32_min(uint32_t a, uint32_t b) { return a < b ? a : b; } -SLANG_FORCE_INLINE uint32_t U32_max(uint32_t a, uint32_t b) { return a > b ? a : b; } +SLANG_FORCE_INLINE uint32_t U32_min(uint32_t a, uint32_t b) +{ + return a < b ? a : b; +} +SLANG_FORCE_INLINE uint32_t U32_max(uint32_t a, uint32_t b) +{ + return a > b ? a : b; +} -SLANG_FORCE_INLINE float U32_asfloat(uint32_t x) { Union32 u; u.u = x; return u.f; } -SLANG_FORCE_INLINE uint32_t U32_asint(int32_t x) { return uint32_t(x); } +SLANG_FORCE_INLINE float U32_asfloat(uint32_t x) +{ + Union32 u; + u.u = x; + return u.f; +} +SLANG_FORCE_INLINE uint32_t U32_asint(int32_t x) +{ + return uint32_t(x); +} SLANG_FORCE_INLINE double U32_asdouble(uint32_t low, uint32_t hi) { @@ -413,7 +702,7 @@ SLANG_FORCE_INLINE uint32_t U32_countbits(uint32_t v) return __builtin_popcount(v); #elif SLANG_PROCESSOR_X86_64 && SLANG_VC return __popcnt(v); -#else +#else uint32_t c = 0; while (v) { @@ -426,21 +715,30 @@ SLANG_FORCE_INLINE uint32_t U32_countbits(uint32_t v) // ----------------------------- U64 ----------------------------------------- -SLANG_FORCE_INLINE uint64_t U64_abs(uint64_t f) { return f; } +SLANG_FORCE_INLINE uint64_t U64_abs(uint64_t f) +{ + return f; +} -SLANG_FORCE_INLINE uint64_t U64_min(uint64_t a, uint64_t b) { return a < b ? a : b; } -SLANG_FORCE_INLINE uint64_t U64_max(uint64_t a, uint64_t b) { return a > b ? a : b; } +SLANG_FORCE_INLINE uint64_t U64_min(uint64_t a, uint64_t b) +{ + return a < b ? a : b; +} +SLANG_FORCE_INLINE uint64_t U64_max(uint64_t a, uint64_t b) +{ + return a > b ? a : b; +} // TODO(JS): We don't define countbits for 64bit in the core module currently. -// It's not clear from documentation if it should return 32 or 64 bits, if it exists. -// 32 bits can always hold the result, and will be implicitly promoted. +// It's not clear from documentation if it should return 32 or 64 bits, if it exists. +// 32 bits can always hold the result, and will be implicitly promoted. SLANG_FORCE_INLINE uint32_t U64_countbits(uint64_t v) { -#if SLANG_GCC_FAMILY && !defined(SLANG_LLVM) +#if SLANG_GCC_FAMILY && !defined(SLANG_LLVM) return uint32_t(__builtin_popcountl(v)); #elif SLANG_PROCESSOR_X86_64 && SLANG_VC return uint32_t(__popcnt64(v)); -#else +#else uint32_t c = 0; while (v) { @@ -453,10 +751,19 @@ SLANG_FORCE_INLINE uint32_t U64_countbits(uint64_t v) // ----------------------------- I64 ----------------------------------------- -SLANG_FORCE_INLINE int64_t I64_abs(int64_t f) { return (f < 0) ? -f : f; } +SLANG_FORCE_INLINE int64_t I64_abs(int64_t f) +{ + return (f < 0) ? -f : f; +} -SLANG_FORCE_INLINE int64_t I64_min(int64_t a, int64_t b) { return a < b ? a : b; } -SLANG_FORCE_INLINE int64_t I64_max(int64_t a, int64_t b) { return a > b ? a : b; } +SLANG_FORCE_INLINE int64_t I64_min(int64_t a, int64_t b) +{ + return a < b ? a : b; +} +SLANG_FORCE_INLINE int64_t I64_max(int64_t a, int64_t b) +{ + return a > b ? a : b; +} // ----------------------------- Interlocked --------------------------------- @@ -465,17 +772,17 @@ SLANG_FORCE_INLINE int64_t I64_max(int64_t a, int64_t b) { return a > b ? a : b; #else // SLANG_LLVM -# ifdef _WIN32 -# include -# endif +#ifdef _WIN32 +#include +#endif SLANG_FORCE_INLINE void InterlockedAdd(uint32_t* dest, uint32_t value, uint32_t* oldValue) { -# ifdef _WIN32 +#ifdef _WIN32 *oldValue = _InterlockedExchangeAdd((long*)dest, (long)value); -# else +#else *oldValue = __sync_fetch_and_add(dest, value); -# endif +#endif } #endif // SLANG_LLVM @@ -492,7 +799,7 @@ SLANG_FORCE_INLINE double _slang_fmod(double x, double y) } #ifdef SLANG_PRELUDE_NAMESPACE -} +} #endif #endif diff --git a/prelude/slang-cpp-types-core.h b/prelude/slang-cpp-types-core.h index 25fe47202..6c0bb7544 100644 --- a/prelude/slang-cpp-types-core.h +++ b/prelude/slang-cpp-types-core.h @@ -2,11 +2,11 @@ #define SLANG_PRELUDE_CPP_TYPES_CORE_H #ifndef SLANG_PRELUDE_ASSERT -# ifdef SLANG_PRELUDE_ENABLE_ASSERT -# define SLANG_PRELUDE_ASSERT(VALUE) assert(VALUE) -# else -# define SLANG_PRELUDE_ASSERT(VALUE) -# endif +#ifdef SLANG_PRELUDE_ENABLE_ASSERT +#define SLANG_PRELUDE_ASSERT(VALUE) assert(VALUE) +#else +#define SLANG_PRELUDE_ASSERT(VALUE) +#endif #endif // Since we are using unsigned arithmatic care is need in this comparison. @@ -15,35 +15,42 @@ // Asserts for bounds checking. // It is assumed index/count are unsigned types. -#define SLANG_BOUND_ASSERT(index, count) SLANG_PRELUDE_ASSERT(index < count); -#define SLANG_BOUND_ASSERT_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_PRELUDE_ASSERT(index <= (sizeInBytes - elemSize) && (index & 3) == 0); +#define SLANG_BOUND_ASSERT(index, count) SLANG_PRELUDE_ASSERT(index < count); +#define SLANG_BOUND_ASSERT_BYTE_ADDRESS(index, elemSize, sizeInBytes) \ + SLANG_PRELUDE_ASSERT(index <= (sizeInBytes - elemSize) && (index & 3) == 0); // Macros to zero index if an access is out of range -#define SLANG_BOUND_ZERO_INDEX(index, count) index = (index < count) ? index : 0; -#define SLANG_BOUND_ZERO_INDEX_BYTE_ADDRESS(index, elemSize, sizeInBytes) index = (index <= (sizeInBytes - elemSize)) ? index : 0; - -// The 'FIX' macro define how the index is fixed. The default is to do nothing. If SLANG_ENABLE_BOUND_ZERO_INDEX -// the fix macro will zero the index, if out of range -#ifdef SLANG_ENABLE_BOUND_ZERO_INDEX -# define SLANG_BOUND_FIX(index, count) SLANG_BOUND_ZERO_INDEX(index, count) -# define SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_BOUND_ZERO_INDEX_BYTE_ADDRESS(index, elemSize, sizeInBytes) -# define SLANG_BOUND_FIX_FIXED_ARRAY(index, count) SLANG_BOUND_ZERO_INDEX(index, count) +#define SLANG_BOUND_ZERO_INDEX(index, count) index = (index < count) ? index : 0; +#define SLANG_BOUND_ZERO_INDEX_BYTE_ADDRESS(index, elemSize, sizeInBytes) \ + index = (index <= (sizeInBytes - elemSize)) ? index : 0; + +// The 'FIX' macro define how the index is fixed. The default is to do nothing. If +// SLANG_ENABLE_BOUND_ZERO_INDEX the fix macro will zero the index, if out of range +#ifdef SLANG_ENABLE_BOUND_ZERO_INDEX +#define SLANG_BOUND_FIX(index, count) SLANG_BOUND_ZERO_INDEX(index, count) +#define SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) \ + SLANG_BOUND_ZERO_INDEX_BYTE_ADDRESS(index, elemSize, sizeInBytes) +#define SLANG_BOUND_FIX_FIXED_ARRAY(index, count) SLANG_BOUND_ZERO_INDEX(index, count) #else -# define SLANG_BOUND_FIX(index, count) -# define SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) -# define SLANG_BOUND_FIX_FIXED_ARRAY(index, count) +#define SLANG_BOUND_FIX(index, count) +#define SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) +#define SLANG_BOUND_FIX_FIXED_ARRAY(index, count) #endif #ifndef SLANG_BOUND_CHECK -# define SLANG_BOUND_CHECK(index, count) SLANG_BOUND_ASSERT(index, count) SLANG_BOUND_FIX(index, count) +#define SLANG_BOUND_CHECK(index, count) \ + SLANG_BOUND_ASSERT(index, count) SLANG_BOUND_FIX(index, count) #endif #ifndef SLANG_BOUND_CHECK_BYTE_ADDRESS -# define SLANG_BOUND_CHECK_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_BOUND_ASSERT_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) +#define SLANG_BOUND_CHECK_BYTE_ADDRESS(index, elemSize, sizeInBytes) \ + SLANG_BOUND_ASSERT_BYTE_ADDRESS(index, elemSize, sizeInBytes) \ + SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) #endif #ifndef SLANG_BOUND_CHECK_FIXED_ARRAY -# define SLANG_BOUND_CHECK_FIXED_ARRAY(index, count) SLANG_BOUND_ASSERT(index, count) SLANG_BOUND_FIX_FIXED_ARRAY(index, count) +#define SLANG_BOUND_CHECK_FIXED_ARRAY(index, count) \ + SLANG_BOUND_ASSERT(index, count) SLANG_BOUND_FIX_FIXED_ARRAY(index, count) #endif struct TypeInfo @@ -51,34 +58,51 @@ struct TypeInfo size_t typeSize; }; -template +template struct FixedArray { - const T& operator[](size_t index) const { SLANG_BOUND_CHECK_FIXED_ARRAY(index, SIZE); return m_data[index]; } - T& operator[](size_t index) { SLANG_BOUND_CHECK_FIXED_ARRAY(index, SIZE); return m_data[index]; } + const T& operator[](size_t index) const + { + SLANG_BOUND_CHECK_FIXED_ARRAY(index, SIZE); + return m_data[index]; + } + T& operator[](size_t index) + { + SLANG_BOUND_CHECK_FIXED_ARRAY(index, SIZE); + return m_data[index]; + } T m_data[SIZE]; }; -// An array that has no specified size, becomes a 'Array'. This stores the size so it can potentially -// do bounds checking. -template +// An array that has no specified size, becomes a 'Array'. This stores the size so it can +// potentially do bounds checking. +template struct Array { - const T& operator[](size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; } - T& operator[](size_t index) { SLANG_BOUND_CHECK(index, count); return data[index]; } + const T& operator[](size_t index) const + { + SLANG_BOUND_CHECK(index, count); + return data[index]; + } + T& operator[](size_t index) + { + SLANG_BOUND_CHECK(index, count); + return data[index]; + } T* data; size_t count; }; -/* Constant buffers become a pointer to the contained type, so ConstantBuffer becomes T* in C++ code. -*/ +/* Constant buffers become a pointer to the contained type, so ConstantBuffer becomes T* in C++ + * code. + */ -template +template struct Vector; -template +template struct Vector { T x; @@ -86,58 +110,54 @@ struct Vector T& operator[](size_t /*index*/) { return x; } operator T() const { return x; } Vector() = default; - Vector(T scalar) - { - x = scalar; - } - template + Vector(T scalar) { x = scalar; } + template Vector(Vector other) { x = (T)other.x; } - template + template Vector(Vector other) { int minSize = 1; - if (otherSize < minSize) minSize = otherSize; + if (otherSize < minSize) + minSize = otherSize; for (int i = 0; i < minSize; i++) (*this)[i] = (T)other[i]; } }; -template +template struct Vector { T x, y; const T& operator[](size_t index) const { return index == 0 ? x : y; } T& operator[](size_t index) { return index == 0 ? x : y; } Vector() = default; - Vector(T scalar) - { - x = y = scalar; - } + Vector(T scalar) { x = y = scalar; } Vector(T _x, T _y) { x = _x; y = _y; } - template + template Vector(Vector other) { x = (T)other.x; y = (T)other.y; } - template + template Vector(Vector other) { int minSize = 2; - if (otherSize < minSize) minSize = otherSize; + if (otherSize < minSize) + minSize = otherSize; for (int i = 0; i < minSize; i++) (*this)[i] = (T)other[i]; } }; -template +template struct Vector { T x, y, z; @@ -145,34 +165,32 @@ struct Vector T& operator[](size_t index) { return *((T*)(this) + index); } Vector() = default; - Vector(T scalar) - { - x = y = z = scalar; - } + Vector(T scalar) { x = y = z = scalar; } Vector(T _x, T _y, T _z) { x = _x; y = _y; z = _z; } - template + template Vector(Vector other) { x = (T)other.x; y = (T)other.y; z = (T)other.z; } - template + template Vector(Vector other) { int minSize = 3; - if (otherSize < minSize) minSize = otherSize; + if (otherSize < minSize) + minSize = otherSize; for (int i = 0; i < minSize; i++) (*this)[i] = (T)other[i]; } }; -template +template struct Vector { T x, y, z, w; @@ -180,10 +198,7 @@ struct Vector const T& operator[](size_t index) const { return *((T*)(this) + index); } T& operator[](size_t index) { return *((T*)(this) + index); } Vector() = default; - Vector(T scalar) - { - x = y = z = w = scalar; - } + Vector(T scalar) { x = y = z = w = scalar; } Vector(T _x, T _y, T _z, T _w) { x = _x; @@ -191,19 +206,22 @@ struct Vector z = _z; w = _w; } - template + template Vector(Vector other) { int minSize = 4; - if (otherSize < minSize) minSize = otherSize; + if (otherSize < minSize) + minSize = otherSize; for (int i = 0; i < minSize; i++) (*this)[i] = (T)other[i]; } - }; template -SLANG_FORCE_INLINE Vector _slang_select(Vector condition, Vector v0, Vector v1) +SLANG_FORCE_INLINE Vector _slang_select( + Vector condition, + Vector v0, + Vector v1) { Vector result; for (int i = 0; i < N; i++) @@ -228,7 +246,7 @@ SLANG_FORCE_INLINE T _slang_vector_get_element(Vector x, int index) template SLANG_FORCE_INLINE const T* _slang_vector_get_element_ptr(const Vector* x, int index) { - return &((*const_cast*>(x))[index]); + return &((*const_cast*>(x))[index]); } template @@ -253,66 +271,70 @@ SLANG_FORCE_INLINE Vector _slang_vector_reshape(const Vector ot typedef uint32_t uint; -#define SLANG_VECTOR_BINARY_OP(T, op) \ - template \ - SLANG_FORCE_INLINE Vector operator op(const Vector& thisVal, const Vector& other) \ - { \ - Vector result;\ - for (int i = 0; i < n; i++) \ - result[i] = thisVal[i] op other[i]; \ - return result;\ - } -#define SLANG_VECTOR_BINARY_COMPARE_OP(T, op) \ - template \ - SLANG_FORCE_INLINE Vector operator op(const Vector& thisVal, const Vector& other) \ - { \ - Vector result;\ - for (int i = 0; i < n; i++) \ - result[i] = thisVal[i] op other[i]; \ - return result;\ - } - -#define SLANG_VECTOR_UNARY_OP(T, op) \ - template \ +#define SLANG_VECTOR_BINARY_OP(T, op) \ + template \ + SLANG_FORCE_INLINE Vector operator op( \ + const Vector& thisVal, \ + const Vector& other) \ + { \ + Vector result; \ + for (int i = 0; i < n; i++) \ + result[i] = thisVal[i] op other[i]; \ + return result; \ + } +#define SLANG_VECTOR_BINARY_COMPARE_OP(T, op) \ + template \ + SLANG_FORCE_INLINE Vector operator op( \ + const Vector& thisVal, \ + const Vector& other) \ + { \ + Vector result; \ + for (int i = 0; i < n; i++) \ + result[i] = thisVal[i] op other[i]; \ + return result; \ + } + +#define SLANG_VECTOR_UNARY_OP(T, op) \ + template \ SLANG_FORCE_INLINE Vector operator op(const Vector& thisVal) \ - { \ - Vector result;\ - for (int i = 0; i < n; i++) \ - result[i] = op thisVal[i]; \ - return result;\ - } -#define SLANG_INT_VECTOR_OPS(T) \ - SLANG_VECTOR_BINARY_OP(T, +)\ - SLANG_VECTOR_BINARY_OP(T, -)\ - SLANG_VECTOR_BINARY_OP(T, *)\ - SLANG_VECTOR_BINARY_OP(T, / )\ - SLANG_VECTOR_BINARY_OP(T, &)\ - SLANG_VECTOR_BINARY_OP(T, |)\ - SLANG_VECTOR_BINARY_OP(T, &&)\ - SLANG_VECTOR_BINARY_OP(T, ||)\ - SLANG_VECTOR_BINARY_OP(T, ^)\ - SLANG_VECTOR_BINARY_OP(T, %)\ - SLANG_VECTOR_BINARY_OP(T, >>)\ - SLANG_VECTOR_BINARY_OP(T, <<)\ - SLANG_VECTOR_BINARY_COMPARE_OP(T, >)\ - SLANG_VECTOR_BINARY_COMPARE_OP(T, <)\ - SLANG_VECTOR_BINARY_COMPARE_OP(T, >=)\ - SLANG_VECTOR_BINARY_COMPARE_OP(T, <=)\ - SLANG_VECTOR_BINARY_COMPARE_OP(T, ==)\ - SLANG_VECTOR_BINARY_COMPARE_OP(T, !=)\ - SLANG_VECTOR_UNARY_OP(T, !)\ + { \ + Vector result; \ + for (int i = 0; i < n; i++) \ + result[i] = op thisVal[i]; \ + return result; \ + } +#define SLANG_INT_VECTOR_OPS(T) \ + SLANG_VECTOR_BINARY_OP(T, +) \ + SLANG_VECTOR_BINARY_OP(T, -) \ + SLANG_VECTOR_BINARY_OP(T, *) \ + SLANG_VECTOR_BINARY_OP(T, /) \ + SLANG_VECTOR_BINARY_OP(T, &) \ + SLANG_VECTOR_BINARY_OP(T, |) \ + SLANG_VECTOR_BINARY_OP(T, &&) \ + SLANG_VECTOR_BINARY_OP(T, ||) \ + SLANG_VECTOR_BINARY_OP(T, ^) \ + SLANG_VECTOR_BINARY_OP(T, %) \ + SLANG_VECTOR_BINARY_OP(T, >>) \ + SLANG_VECTOR_BINARY_OP(T, <<) \ + SLANG_VECTOR_BINARY_COMPARE_OP(T, >) \ + SLANG_VECTOR_BINARY_COMPARE_OP(T, <) \ + SLANG_VECTOR_BINARY_COMPARE_OP(T, >=) \ + SLANG_VECTOR_BINARY_COMPARE_OP(T, <=) \ + SLANG_VECTOR_BINARY_COMPARE_OP(T, ==) \ + SLANG_VECTOR_BINARY_COMPARE_OP(T, !=) \ + SLANG_VECTOR_UNARY_OP(T, !) \ SLANG_VECTOR_UNARY_OP(T, ~) -#define SLANG_FLOAT_VECTOR_OPS(T) \ - SLANG_VECTOR_BINARY_OP(T, +)\ - SLANG_VECTOR_BINARY_OP(T, -)\ - SLANG_VECTOR_BINARY_OP(T, *)\ - SLANG_VECTOR_BINARY_OP(T, /)\ - SLANG_VECTOR_UNARY_OP(T, -)\ - SLANG_VECTOR_BINARY_COMPARE_OP(T, >)\ - SLANG_VECTOR_BINARY_COMPARE_OP(T, <)\ - SLANG_VECTOR_BINARY_COMPARE_OP(T, >=)\ - SLANG_VECTOR_BINARY_COMPARE_OP(T, <=)\ - SLANG_VECTOR_BINARY_COMPARE_OP(T, ==)\ +#define SLANG_FLOAT_VECTOR_OPS(T) \ + SLANG_VECTOR_BINARY_OP(T, +) \ + SLANG_VECTOR_BINARY_OP(T, -) \ + SLANG_VECTOR_BINARY_OP(T, *) \ + SLANG_VECTOR_BINARY_OP(T, /) \ + SLANG_VECTOR_UNARY_OP(T, -) \ + SLANG_VECTOR_BINARY_COMPARE_OP(T, >) \ + SLANG_VECTOR_BINARY_COMPARE_OP(T, <) \ + SLANG_VECTOR_BINARY_COMPARE_OP(T, >=) \ + SLANG_VECTOR_BINARY_COMPARE_OP(T, <=) \ + SLANG_VECTOR_BINARY_COMPARE_OP(T, ==) \ SLANG_VECTOR_BINARY_COMPARE_OP(T, !=) SLANG_INT_VECTOR_OPS(bool) @@ -328,14 +350,14 @@ SLANG_INT_VECTOR_OPS(uint64_t) SLANG_FLOAT_VECTOR_OPS(float) SLANG_FLOAT_VECTOR_OPS(double) -#define SLANG_VECTOR_INT_NEG_OP(T) \ - template\ +#define SLANG_VECTOR_INT_NEG_OP(T) \ + template \ Vector operator-(const Vector& thisVal) \ - { \ - Vector result;\ - for (int i = 0; i < N; i++) \ - result[i] = 0 - thisVal[i]; \ - return result;\ + { \ + Vector result; \ + for (int i = 0; i < N; i++) \ + result[i] = 0 - thisVal[i]; \ + return result; \ } SLANG_VECTOR_INT_NEG_OP(int) SLANG_VECTOR_INT_NEG_OP(int8_t) @@ -346,14 +368,14 @@ SLANG_VECTOR_INT_NEG_OP(uint8_t) SLANG_VECTOR_INT_NEG_OP(uint16_t) SLANG_VECTOR_INT_NEG_OP(uint64_t) -#define SLANG_FLOAT_VECTOR_MOD(T)\ - template \ +#define SLANG_FLOAT_VECTOR_MOD(T) \ + template \ Vector operator%(const Vector& left, const Vector& right) \ - {\ - Vector result;\ - for (int i = 0; i < N; i++) \ - result[i] = _slang_fmod(left[i], right[i]); \ - return result;\ + { \ + Vector result; \ + for (int i = 0; i < N; i++) \ + result[i] = _slang_fmod(left[i], right[i]); \ + return result; \ } SLANG_FLOAT_VECTOR_MOD(float) @@ -366,7 +388,7 @@ SLANG_FLOAT_VECTOR_MOD(double) #undef SLANG_VECTOR_INT_NEG_OP #undef SLANG_FLOAT_VECTOR_MOD -template +template struct Matrix { Vector rows[ROWS]; @@ -377,10 +399,7 @@ struct Matrix for (int i = 0; i < ROWS; i++) rows[i] = Vector(scalar); } - Matrix(const Vector& row0) - { - rows[0] = row0; - } + Matrix(const Vector& row0) { rows[0] = row0; } Matrix(const Vector& row0, const Vector& row1) { rows[0] = row0; @@ -392,7 +411,11 @@ struct Matrix rows[1] = row1; rows[2] = row2; } - Matrix(const Vector& row0, const Vector& row1, const Vector& row2, const Vector& row3) + Matrix( + const Vector& row0, + const Vector& row1, + const Vector& row2, + const Vector& row3) { rows[0] = row0; rows[1] = row1; @@ -404,116 +427,188 @@ struct Matrix { int minRow = ROWS; int minCol = COLS; - if (minRow > otherRow) minRow = otherRow; - if (minCol > otherCol) minCol = otherCol; + if (minRow > otherRow) + minRow = otherRow; + if (minCol > otherCol) + minCol = otherCol; for (int i = 0; i < minRow; i++) for (int j = 0; j < minCol; j++) rows[i][j] = (T)other.rows[i][j]; } Matrix(T v0, T v1, T v2, T v3) { - rows[0][0] = v0; rows[0][1] = v1; - rows[1][0] = v2; rows[1][1] = v3; + rows[0][0] = v0; + rows[0][1] = v1; + rows[1][0] = v2; + rows[1][1] = v3; } Matrix(T v0, T v1, T v2, T v3, T v4, T v5) { if (COLS == 3) { - rows[0][0] = v0; rows[0][1] = v1; rows[0][2] = v2; - rows[1][0] = v3; rows[1][1] = v4; rows[1][2] = v5; + rows[0][0] = v0; + rows[0][1] = v1; + rows[0][2] = v2; + rows[1][0] = v3; + rows[1][1] = v4; + rows[1][2] = v5; } else { - rows[0][0] = v0; rows[0][1] = v1; - rows[1][0] = v2; rows[1][1] = v3; - rows[2][0] = v4; rows[2][1] = v5; + rows[0][0] = v0; + rows[0][1] = v1; + rows[1][0] = v2; + rows[1][1] = v3; + rows[2][0] = v4; + rows[2][1] = v5; } } Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7) { if (COLS == 4) { - rows[0][0] = v0; rows[0][1] = v1; rows[0][2] = v2; rows[0][3] = v3; - rows[1][0] = v4; rows[1][1] = v5; rows[1][2] = v6; rows[1][3] = v7; + rows[0][0] = v0; + rows[0][1] = v1; + rows[0][2] = v2; + rows[0][3] = v3; + rows[1][0] = v4; + rows[1][1] = v5; + rows[1][2] = v6; + rows[1][3] = v7; } else { - rows[0][0] = v0; rows[0][1] = v1; - rows[1][0] = v2; rows[1][1] = v3; - rows[2][0] = v4; rows[2][1] = v5; - rows[3][0] = v6; rows[3][1] = v7; + rows[0][0] = v0; + rows[0][1] = v1; + rows[1][0] = v2; + rows[1][1] = v3; + rows[2][0] = v4; + rows[2][1] = v5; + rows[3][0] = v6; + rows[3][1] = v7; } } Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8) { - rows[0][0] = v0; rows[0][1] = v1; rows[0][2] = v2; - rows[1][0] = v3; rows[1][1] = v4; rows[1][2] = v5; - rows[2][0] = v6; rows[2][1] = v7; rows[2][2] = v8; + rows[0][0] = v0; + rows[0][1] = v1; + rows[0][2] = v2; + rows[1][0] = v3; + rows[1][1] = v4; + rows[1][2] = v5; + rows[2][0] = v6; + rows[2][1] = v7; + rows[2][2] = v8; } Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11) { if (COLS == 4) { - rows[0][0] = v0; rows[0][1] = v1; rows[0][2] = v2; rows[0][3] = v3; - rows[1][0] = v4; rows[1][1] = v5; rows[1][2] = v6; rows[1][3] = v7; - rows[2][0] = v8; rows[2][1] = v9; rows[2][2] = v10; rows[2][3] = v11; + rows[0][0] = v0; + rows[0][1] = v1; + rows[0][2] = v2; + rows[0][3] = v3; + rows[1][0] = v4; + rows[1][1] = v5; + rows[1][2] = v6; + rows[1][3] = v7; + rows[2][0] = v8; + rows[2][1] = v9; + rows[2][2] = v10; + rows[2][3] = v11; } else { - rows[0][0] = v0; rows[0][1] = v1; rows[0][2] = v2; - rows[1][0] = v3; rows[1][1] = v4; rows[1][2] = v5; - rows[2][0] = v6; rows[2][1] = v7; rows[2][2] = v8; - rows[3][0] = v9; rows[3][1] = v10; rows[3][2] = v11; + rows[0][0] = v0; + rows[0][1] = v1; + rows[0][2] = v2; + rows[1][0] = v3; + rows[1][1] = v4; + rows[1][2] = v5; + rows[2][0] = v6; + rows[2][1] = v7; + rows[2][2] = v8; + rows[3][0] = v9; + rows[3][1] = v10; + rows[3][2] = v11; } } - Matrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11, T v12, T v13, T v14, T v15) + Matrix( + T v0, + T v1, + T v2, + T v3, + T v4, + T v5, + T v6, + T v7, + T v8, + T v9, + T v10, + T v11, + T v12, + T v13, + T v14, + T v15) { - rows[0][0] = v0; rows[0][1] = v1; rows[0][2] = v2; rows[0][3] = v3; - rows[1][0] = v4; rows[1][1] = v5; rows[1][2] = v6; rows[1][3] = v7; - rows[2][0] = v8; rows[2][1] = v9; rows[2][2] = v10; rows[2][3] = v11; - rows[3][0] = v12; rows[3][1] = v13; rows[3][2] = v14; rows[3][3] = v15; + rows[0][0] = v0; + rows[0][1] = v1; + rows[0][2] = v2; + rows[0][3] = v3; + rows[1][0] = v4; + rows[1][1] = v5; + rows[1][2] = v6; + rows[1][3] = v7; + rows[2][0] = v8; + rows[2][1] = v9; + rows[2][2] = v10; + rows[2][3] = v11; + rows[3][0] = v12; + rows[3][1] = v13; + rows[3][2] = v14; + rows[3][3] = v15; } }; -#define SLANG_MATRIX_BINARY_OP(T, op) \ - template \ +#define SLANG_MATRIX_BINARY_OP(T, op) \ + template \ Matrix operator op(const Matrix& thisVal, const Matrix& other) \ - { \ - Matrix result;\ - for (int i = 0; i < R; i++) \ - for (int j = 0; j < C; j++) \ - result.rows[i][j] = thisVal.rows[i][j] op other.rows[i][j]; \ - return result;\ + { \ + Matrix result; \ + for (int i = 0; i < R; i++) \ + for (int j = 0; j < C; j++) \ + result.rows[i][j] = thisVal.rows[i][j] op other.rows[i][j]; \ + return result; \ } -#define SLANG_MATRIX_UNARY_OP(T, op) \ - template \ +#define SLANG_MATRIX_UNARY_OP(T, op) \ + template \ Matrix operator op(const Matrix& thisVal) \ - { \ - Matrix result;\ - for (int i = 0; i < R; i++) \ - for (int j = 0; j < C; j++) \ - result[i].rows[i][j] = op thisVal.rows[i][j]; \ - return result;\ - } -#define SLANG_INT_MATRIX_OPS(T) \ - SLANG_MATRIX_BINARY_OP(T, +)\ - SLANG_MATRIX_BINARY_OP(T, -)\ - SLANG_MATRIX_BINARY_OP(T, *)\ - SLANG_MATRIX_BINARY_OP(T, / )\ - SLANG_MATRIX_BINARY_OP(T, &)\ - SLANG_MATRIX_BINARY_OP(T, |)\ - SLANG_MATRIX_BINARY_OP(T, &&)\ - SLANG_MATRIX_BINARY_OP(T, ||)\ - SLANG_MATRIX_BINARY_OP(T, ^)\ - SLANG_MATRIX_BINARY_OP(T, %)\ - SLANG_MATRIX_UNARY_OP(T, !)\ + { \ + Matrix result; \ + for (int i = 0; i < R; i++) \ + for (int j = 0; j < C; j++) \ + result[i].rows[i][j] = op thisVal.rows[i][j]; \ + return result; \ + } +#define SLANG_INT_MATRIX_OPS(T) \ + SLANG_MATRIX_BINARY_OP(T, +) \ + SLANG_MATRIX_BINARY_OP(T, -) \ + SLANG_MATRIX_BINARY_OP(T, *) \ + SLANG_MATRIX_BINARY_OP(T, /) \ + SLANG_MATRIX_BINARY_OP(T, &) \ + SLANG_MATRIX_BINARY_OP(T, |) \ + SLANG_MATRIX_BINARY_OP(T, &&) \ + SLANG_MATRIX_BINARY_OP(T, ||) \ + SLANG_MATRIX_BINARY_OP(T, ^) \ + SLANG_MATRIX_BINARY_OP(T, %) \ + SLANG_MATRIX_UNARY_OP(T, !) \ SLANG_MATRIX_UNARY_OP(T, ~) #define SLANG_FLOAT_MATRIX_OPS(T) \ - SLANG_MATRIX_BINARY_OP(T, +)\ - SLANG_MATRIX_BINARY_OP(T, -)\ - SLANG_MATRIX_BINARY_OP(T, *)\ - SLANG_MATRIX_BINARY_OP(T, /)\ + SLANG_MATRIX_BINARY_OP(T, +) \ + SLANG_MATRIX_BINARY_OP(T, -) \ + SLANG_MATRIX_BINARY_OP(T, *) \ + SLANG_MATRIX_BINARY_OP(T, /) \ SLANG_MATRIX_UNARY_OP(T, -) SLANG_INT_MATRIX_OPS(int) SLANG_INT_MATRIX_OPS(int8_t) @@ -527,38 +622,38 @@ SLANG_INT_MATRIX_OPS(uint64_t) SLANG_FLOAT_MATRIX_OPS(float) SLANG_FLOAT_MATRIX_OPS(double) -#define SLANG_MATRIX_INT_NEG_OP(T) \ - template\ +#define SLANG_MATRIX_INT_NEG_OP(T) \ + template \ SLANG_FORCE_INLINE Matrix operator-(Matrix thisVal) \ - { \ - Matrix result;\ - for (int i = 0; i < R; i++) \ - for (int j = 0; j < C; j++) \ - result.rows[i][j] = 0 - thisVal.rows[i][j]; \ - return result;\ - } - SLANG_MATRIX_INT_NEG_OP(int) - SLANG_MATRIX_INT_NEG_OP(int8_t) - SLANG_MATRIX_INT_NEG_OP(int16_t) - SLANG_MATRIX_INT_NEG_OP(int64_t) - SLANG_MATRIX_INT_NEG_OP(uint) - SLANG_MATRIX_INT_NEG_OP(uint8_t) - SLANG_MATRIX_INT_NEG_OP(uint16_t) - SLANG_MATRIX_INT_NEG_OP(uint64_t) - -#define SLANG_FLOAT_MATRIX_MOD(T)\ - template \ + { \ + Matrix result; \ + for (int i = 0; i < R; i++) \ + for (int j = 0; j < C; j++) \ + result.rows[i][j] = 0 - thisVal.rows[i][j]; \ + return result; \ + } +SLANG_MATRIX_INT_NEG_OP(int) +SLANG_MATRIX_INT_NEG_OP(int8_t) +SLANG_MATRIX_INT_NEG_OP(int16_t) +SLANG_MATRIX_INT_NEG_OP(int64_t) +SLANG_MATRIX_INT_NEG_OP(uint) +SLANG_MATRIX_INT_NEG_OP(uint8_t) +SLANG_MATRIX_INT_NEG_OP(uint16_t) +SLANG_MATRIX_INT_NEG_OP(uint64_t) + +#define SLANG_FLOAT_MATRIX_MOD(T) \ + template \ SLANG_FORCE_INLINE Matrix operator%(Matrix left, Matrix right) \ - {\ - Matrix result;\ - for (int i = 0; i < R; i++) \ - for (int j = 0; j < C; j++) \ - result.rows[i][j] = _slang_fmod(left.rows[i][j], right.rows[i][j]); \ - return result;\ + { \ + Matrix result; \ + for (int i = 0; i < R; i++) \ + for (int j = 0; j < C; j++) \ + result.rows[i][j] = _slang_fmod(left.rows[i][j], right.rows[i][j]); \ + return result; \ } - SLANG_FLOAT_MATRIX_MOD(float) - SLANG_FLOAT_MATRIX_MOD(double) +SLANG_FLOAT_MATRIX_MOD(float) +SLANG_FLOAT_MATRIX_MOD(double) #undef SLANG_FLOAT_MATRIX_MOD #undef SLANG_MATRIX_BINARY_OP #undef SLANG_MATRIX_UNARY_OP @@ -574,5 +669,3 @@ TResult slang_bit_cast(TInput val) } #endif - - diff --git a/prelude/slang-cpp-types.h b/prelude/slang-cpp-types.h index 3f805a8b7..010ab8d6c 100644 --- a/prelude/slang-cpp-types.h +++ b/prelude/slang-cpp-types.h @@ -2,11 +2,12 @@ #define SLANG_PRELUDE_CPP_TYPES_H #ifdef SLANG_PRELUDE_NAMESPACE -namespace SLANG_PRELUDE_NAMESPACE { +namespace SLANG_PRELUDE_NAMESPACE +{ #endif #ifndef SLANG_FORCE_INLINE -# define SLANG_FORCE_INLINE inline +#define SLANG_FORCE_INLINE inline #endif #include "slang-cpp-types-core.h" @@ -23,8 +24,8 @@ typedef Vector uint2; typedef Vector uint3; typedef Vector uint4; -// We can just map `NonUniformResourceIndex` type directly to the index type on CPU, as CPU does not require -// any special handling around such accesses. +// We can just map `NonUniformResourceIndex` type directly to the index type on CPU, as CPU does not +// require any special handling around such accesses. typedef size_t NonUniformResourceIndex; // ----------------------------- ResourceType ----------------------------------------- @@ -32,47 +33,87 @@ typedef size_t NonUniformResourceIndex; // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-structuredbuffer-getdimensions // Missing Load(_In_ int Location, _Out_ uint Status); -template +template struct RWStructuredBuffer { - SLANG_FORCE_INLINE T& operator[](size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; } - const T& Load(size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; } - void GetDimensions(uint32_t* outNumStructs, uint32_t* outStride) { *outNumStructs = uint32_t(count); *outStride = uint32_t(sizeof(T)); } - + SLANG_FORCE_INLINE T& operator[](size_t index) const + { + SLANG_BOUND_CHECK(index, count); + return data[index]; + } + const T& Load(size_t index) const + { + SLANG_BOUND_CHECK(index, count); + return data[index]; + } + void GetDimensions(uint32_t* outNumStructs, uint32_t* outStride) + { + *outNumStructs = uint32_t(count); + *outStride = uint32_t(sizeof(T)); + } + T* data; size_t count; }; -template +template struct StructuredBuffer { - SLANG_FORCE_INLINE const T& operator[](size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; } - const T& Load(size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; } - void GetDimensions(uint32_t* outNumStructs, uint32_t* outStride) { *outNumStructs = uint32_t(count); *outStride = uint32_t(sizeof(T)); } - + SLANG_FORCE_INLINE const T& operator[](size_t index) const + { + SLANG_BOUND_CHECK(index, count); + return data[index]; + } + const T& Load(size_t index) const + { + SLANG_BOUND_CHECK(index, count); + return data[index]; + } + void GetDimensions(uint32_t* outNumStructs, uint32_t* outStride) + { + *outNumStructs = uint32_t(count); + *outStride = uint32_t(sizeof(T)); + } + T* data; size_t count; }; -template +template struct RWBuffer { - SLANG_FORCE_INLINE T& operator[](size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; } - const T& Load(size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; } + SLANG_FORCE_INLINE T& operator[](size_t index) const + { + SLANG_BOUND_CHECK(index, count); + return data[index]; + } + const T& Load(size_t index) const + { + SLANG_BOUND_CHECK(index, count); + return data[index]; + } void GetDimensions(uint32_t* outCount) { *outCount = uint32_t(count); } - + T* data; size_t count; }; -template +template struct Buffer { - SLANG_FORCE_INLINE const T& operator[](size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; } - const T& Load(size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; } + SLANG_FORCE_INLINE const T& operator[](size_t index) const + { + SLANG_BOUND_CHECK(index, count); + return data[index]; + } + const T& Load(size_t index) const + { + SLANG_BOUND_CHECK(index, count); + return data[index]; + } void GetDimensions(uint32_t* outCount) { *outCount = uint32_t(count); } - + T* data; size_t count; }; @@ -81,28 +122,28 @@ struct Buffer struct ByteAddressBuffer { void GetDimensions(uint32_t* outDim) const { *outDim = uint32_t(sizeInBytes); } - uint32_t Load(size_t index) const - { + uint32_t Load(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes); - return data[index >> 2]; + return data[index >> 2]; } - uint2 Load2(size_t index) const - { + uint2 Load2(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes); - const size_t dataIdx = index >> 2; - return uint2{data[dataIdx], data[dataIdx + 1]}; + const size_t dataIdx = index >> 2; + return uint2{data[dataIdx], data[dataIdx + 1]}; } - uint3 Load3(size_t index) const - { + uint3 Load3(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes); - const size_t dataIdx = index >> 2; - return uint3{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2]}; + const size_t dataIdx = index >> 2; + return uint3{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2]}; } - uint4 Load4(size_t index) const - { + uint4 Load4(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes); - const size_t dataIdx = index >> 2; - return uint4{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2], data[dataIdx + 3]}; + const size_t dataIdx = index >> 2; + return uint4{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2], data[dataIdx + 3]}; } template T Load(size_t index) const @@ -110,40 +151,40 @@ struct ByteAddressBuffer SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes); return *(const T*)(((const char*)data) + index); } - + const uint32_t* data; - size_t sizeInBytes; //< Must be multiple of 4 + size_t sizeInBytes; //< Must be multiple of 4 }; // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-rwbyteaddressbuffer -// Missing support for Atomic operations +// Missing support for Atomic operations // Missing support for Load with status struct RWByteAddressBuffer { void GetDimensions(uint32_t* outDim) const { *outDim = uint32_t(sizeInBytes); } - - uint32_t Load(size_t index) const - { + + uint32_t Load(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes); - return data[index >> 2]; + return data[index >> 2]; } - uint2 Load2(size_t index) const - { + uint2 Load2(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes); - const size_t dataIdx = index >> 2; - return uint2{data[dataIdx], data[dataIdx + 1]}; + const size_t dataIdx = index >> 2; + return uint2{data[dataIdx], data[dataIdx + 1]}; } - uint3 Load3(size_t index) const - { + uint3 Load3(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes); - const size_t dataIdx = index >> 2; - return uint3{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2]}; + const size_t dataIdx = index >> 2; + return uint3{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2]}; } - uint4 Load4(size_t index) const - { + uint4 Load4(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes); - const size_t dataIdx = index >> 2; - return uint4{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2], data[dataIdx + 3]}; + const size_t dataIdx = index >> 2; + return uint4{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2], data[dataIdx + 3]}; } template T Load(size_t index) const @@ -152,30 +193,30 @@ struct RWByteAddressBuffer return *(const T*)(((const char*)data) + index); } - void Store(size_t index, uint32_t v) const - { + void Store(size_t index, uint32_t v) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes); - data[index >> 2] = v; + data[index >> 2] = v; } - void Store2(size_t index, uint2 v) const - { + void Store2(size_t index, uint2 v) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes); - const size_t dataIdx = index >> 2; + const size_t dataIdx = index >> 2; data[dataIdx + 0] = v.x; data[dataIdx + 1] = v.y; } - void Store3(size_t index, uint3 v) const - { + void Store3(size_t index, uint3 v) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes); - const size_t dataIdx = index >> 2; + const size_t dataIdx = index >> 2; data[dataIdx + 0] = v.x; data[dataIdx + 1] = v.y; data[dataIdx + 2] = v.z; } - void Store4(size_t index, uint4 v) const - { + void Store4(size_t index, uint4 v) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes); - const size_t dataIdx = index >> 2; + const size_t dataIdx = index >> 2; data[dataIdx + 0] = v.x; data[dataIdx + 1] = v.y; data[dataIdx + 2] = v.z; @@ -189,7 +230,7 @@ struct RWByteAddressBuffer } uint32_t* data; - size_t sizeInBytes; //< Must be multiple of 4 + size_t sizeInBytes; //< Must be multiple of 4 }; struct ISamplerState; @@ -206,7 +247,7 @@ struct SamplerComparisonState }; #ifndef SLANG_RESOURCE_SHAPE -# define SLANG_RESOURCE_SHAPE +#define SLANG_RESOURCE_SHAPE typedef unsigned int SlangResourceShape; enum { @@ -243,7 +284,7 @@ enum }; #endif -// +// struct TextureDimensions { void reset() @@ -259,25 +300,25 @@ struct TextureDimensions int count = 0; switch (baseShape) { - case SLANG_TEXTURE_1D: + case SLANG_TEXTURE_1D: { outDims[count++] = width; break; } - case SLANG_TEXTURE_2D: + case SLANG_TEXTURE_2D: { outDims[count++] = width; outDims[count++] = height; break; } - case SLANG_TEXTURE_3D: + case SLANG_TEXTURE_3D: { outDims[count++] = width; outDims[count++] = height; outDims[count++] = depth; break; } - case SLANG_TEXTURE_CUBE: + case SLANG_TEXTURE_CUBE: { outDims[count++] = width; outDims[count++] = height; @@ -298,19 +339,19 @@ struct TextureDimensions int count = 0; switch (baseShape) { - case SLANG_TEXTURE_1D: + case SLANG_TEXTURE_1D: { outDims[count++] = width; break; } - case SLANG_TEXTURE_CUBE: - case SLANG_TEXTURE_2D: + case SLANG_TEXTURE_CUBE: + case SLANG_TEXTURE_2D: { outDims[count++] = width; outDims[count++] = height; break; } - case SLANG_TEXTURE_3D: + case SLANG_TEXTURE_3D: { outDims[count++] = width; outDims[count++] = height; @@ -345,97 +386,146 @@ struct TextureDimensions uint32_t shape; uint32_t width, height, depth; uint32_t numberOfLevels; - uint32_t arrayElementCount; ///< For array types, 0 otherwise + uint32_t arrayElementCount; ///< For array types, 0 otherwise }; - - - // Texture struct ITexture { virtual TextureDimensions GetDimensions(int mipLevel = -1) = 0; virtual void Load(const int32_t* v, void* outData, size_t dataSize) = 0; - virtual void Sample(SamplerState samplerState, const float* loc, void* outData, size_t dataSize) = 0; - virtual void SampleLevel(SamplerState samplerState, const float* loc, float level, void* outData, size_t dataSize) = 0; + virtual void Sample( + SamplerState samplerState, + const float* loc, + void* outData, + size_t dataSize) = 0; + virtual void SampleLevel( + SamplerState samplerState, + const float* loc, + float level, + void* outData, + size_t dataSize) = 0; }; -template +template struct Texture1D { void GetDimensions(uint32_t* outWidth) { *outWidth = texture->GetDimensions().width; } - void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outNumberOfLevels) - { - auto dims = texture->GetDimensions(mipLevel); - *outWidth = dims.width; - *outNumberOfLevels = dims.numberOfLevels; + void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outNumberOfLevels) + { + auto dims = texture->GetDimensions(mipLevel); + *outWidth = dims.width; + *outNumberOfLevels = dims.numberOfLevels; } - + void GetDimensions(float* outWidth) { *outWidth = texture->GetDimensions().width; } - void GetDimensions(uint32_t mipLevel, float* outWidth, float* outNumberOfLevels) - { - auto dims = texture->GetDimensions(mipLevel); - *outWidth = dims.width; - *outNumberOfLevels = dims.numberOfLevels; + void GetDimensions(uint32_t mipLevel, float* outWidth, float* outNumberOfLevels) + { + auto dims = texture->GetDimensions(mipLevel); + *outWidth = dims.width; + *outNumberOfLevels = dims.numberOfLevels; + } + + T Load(const int2& loc) const + { + T out; + texture->Load(&loc.x, &out, sizeof(out)); + return out; } - - T Load(const int2& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; } - T Sample(SamplerState samplerState, float loc) const { T out; texture->Sample(samplerState, &loc, &out, sizeof(out)); return out; } - T SampleLevel(SamplerState samplerState, float loc, float level) { T out; texture->SampleLevel(samplerState, &loc, level, &out, sizeof(out)); return out; } - - ITexture* texture; + T Sample(SamplerState samplerState, float loc) const + { + T out; + texture->Sample(samplerState, &loc, &out, sizeof(out)); + return out; + } + T SampleLevel(SamplerState samplerState, float loc, float level) + { + T out; + texture->SampleLevel(samplerState, &loc, level, &out, sizeof(out)); + return out; + } + + ITexture* texture; }; -template +template struct Texture2D { - void GetDimensions(uint32_t* outWidth, uint32_t* outHeight) - { - const auto dims = texture->GetDimensions(); - *outWidth = dims.width; - *outHeight = dims.height; + void GetDimensions(uint32_t* outWidth, uint32_t* outHeight) + { + const auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; } - void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + uint32_t* outWidth, + uint32_t* outHeight, + uint32_t* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; *outHeight = dims.height; *outNumberOfLevels = dims.numberOfLevels; } - void GetDimensions(float* outWidth, float* outHeight) - { - const auto dims = texture->GetDimensions(); - *outWidth = dims.width; - *outHeight = dims.height; + void GetDimensions(float* outWidth, float* outHeight) + { + const auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; } - void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outHeight, + float* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; *outHeight = dims.height; *outNumberOfLevels = dims.numberOfLevels; } - - T Load(const int3& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; } - T Sample(SamplerState samplerState, const float2& loc) const { T out; texture->Sample(samplerState, &loc.x, &out, sizeof(out)); return out; } - T SampleLevel(SamplerState samplerState, const float2& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); return out; } - - ITexture* texture; + + T Load(const int3& loc) const + { + T out; + texture->Load(&loc.x, &out, sizeof(out)); + return out; + } + T Sample(SamplerState samplerState, const float2& loc) const + { + T out; + texture->Sample(samplerState, &loc.x, &out, sizeof(out)); + return out; + } + T SampleLevel(SamplerState samplerState, const float2& loc, float level) + { + T out; + texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); + return out; + } + + ITexture* texture; }; -template +template struct Texture3D { void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outDepth) { - const auto dims = texture->GetDimensions(); - *outWidth = dims.width; - *outHeight = dims.height; + const auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; *outDepth = dims.depth; } - void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outDepth, uint32_t* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + uint32_t* outWidth, + uint32_t* outHeight, + uint32_t* outDepth, + uint32_t* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; @@ -445,12 +535,17 @@ struct Texture3D } void GetDimensions(float* outWidth, float* outHeight, float* outDepth) { - const auto dims = texture->GetDimensions(); - *outWidth = dims.width; - *outHeight = dims.height; + const auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; *outDepth = dims.depth; } - void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outDepth, float* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outHeight, + float* outDepth, + float* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; @@ -458,78 +553,144 @@ struct Texture3D *outDepth = dims.depth; *outNumberOfLevels = dims.numberOfLevels; } - - T Load(const int4& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; } - T Sample(SamplerState samplerState, const float3& loc) const { T out; texture->Sample(samplerState, &loc.x, &out, sizeof(out)); return out; } - T SampleLevel(SamplerState samplerState, const float3& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); return out; } - - ITexture* texture; + + T Load(const int4& loc) const + { + T out; + texture->Load(&loc.x, &out, sizeof(out)); + return out; + } + T Sample(SamplerState samplerState, const float3& loc) const + { + T out; + texture->Sample(samplerState, &loc.x, &out, sizeof(out)); + return out; + } + T SampleLevel(SamplerState samplerState, const float3& loc, float level) + { + T out; + texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); + return out; + } + + ITexture* texture; }; -template +template struct TextureCube { - void GetDimensions(uint32_t* outWidth, uint32_t* outHeight) - { - const auto dims = texture->GetDimensions(); - *outWidth = dims.width; - *outHeight = dims.height; + void GetDimensions(uint32_t* outWidth, uint32_t* outHeight) + { + const auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; } - void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + uint32_t* outWidth, + uint32_t* outHeight, + uint32_t* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; *outHeight = dims.height; *outNumberOfLevels = dims.numberOfLevels; } - void GetDimensions(float* outWidth, float* outHeight) - { - const auto dims = texture->GetDimensions(); - *outWidth = dims.width; - *outHeight = dims.height; + void GetDimensions(float* outWidth, float* outHeight) + { + const auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; } - void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outHeight, + float* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; *outHeight = dims.height; *outNumberOfLevels = dims.numberOfLevels; } - - T Sample(SamplerState samplerState, const float3& loc) const { T out; texture->Sample(samplerState, &loc.x, &out, sizeof(out)); return out; } - T SampleLevel(SamplerState samplerState, const float3& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); return out; } - - ITexture* texture; + + T Sample(SamplerState samplerState, const float3& loc) const + { + T out; + texture->Sample(samplerState, &loc.x, &out, sizeof(out)); + return out; + } + T SampleLevel(SamplerState samplerState, const float3& loc, float level) + { + T out; + texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); + return out; + } + + ITexture* texture; }; -template +template struct Texture1DArray { - void GetDimensions(uint32_t* outWidth, uint32_t* outElements) { auto dims = texture->GetDimensions(); *outWidth = dims.width; *outElements = dims.arrayElementCount; } - void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outElements, uint32_t* outNumberOfLevels) + void GetDimensions(uint32_t* outWidth, uint32_t* outElements) { - auto dims = texture->GetDimensions(mipLevel); - *outWidth = dims.width; + auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outElements = dims.arrayElementCount; + } + void GetDimensions( + uint32_t mipLevel, + uint32_t* outWidth, + uint32_t* outElements, + uint32_t* outNumberOfLevels) + { + auto dims = texture->GetDimensions(mipLevel); + *outWidth = dims.width; *outNumberOfLevels = dims.numberOfLevels; - *outElements = dims.arrayElementCount; - } - void GetDimensions(float* outWidth, float* outElements) { auto dims = texture->GetDimensions(); *outWidth = dims.width; *outElements = dims.arrayElementCount; } - void GetDimensions(uint32_t mipLevel, float* outWidth, float* outElements, float* outNumberOfLevels) + *outElements = dims.arrayElementCount; + } + void GetDimensions(float* outWidth, float* outElements) { - auto dims = texture->GetDimensions(mipLevel); - *outWidth = dims.width; + auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outElements = dims.arrayElementCount; + } + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outElements, + float* outNumberOfLevels) + { + auto dims = texture->GetDimensions(mipLevel); + *outWidth = dims.width; *outNumberOfLevels = dims.numberOfLevels; - *outElements = dims.arrayElementCount; + *outElements = dims.arrayElementCount; + } + + T Load(const int3& loc) const + { + T out; + texture->Load(&loc.x, &out, sizeof(out)); + return out; + } + T Sample(SamplerState samplerState, const float2& loc) const + { + T out; + texture->Sample(samplerState, &loc.x, &out, sizeof(out)); + return out; + } + T SampleLevel(SamplerState samplerState, const float2& loc, float level) + { + T out; + texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); + return out; } - - T Load(const int3& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; } - T Sample(SamplerState samplerState, const float2& loc) const { T out; texture->Sample(samplerState, &loc.x, &out, sizeof(out)); return out; } - T SampleLevel(SamplerState samplerState, const float2& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); return out; } - - ITexture* texture; + + ITexture* texture; }; -template +template struct Texture2DArray { void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements) @@ -539,7 +700,12 @@ struct Texture2DArray *outHeight = dims.height; *outElements = dims.arrayElementCount; } - void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements, uint32_t* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + uint32_t* outWidth, + uint32_t* outHeight, + uint32_t* outElements, + uint32_t* outNumberOfLevels) { auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; @@ -547,7 +713,7 @@ struct Texture2DArray *outElements = dims.arrayElementCount; *outNumberOfLevels = dims.numberOfLevels; } - + void GetDimensions(uint32_t* outWidth, float* outHeight, float* outElements) { auto dims = texture->GetDimensions(); @@ -555,7 +721,12 @@ struct Texture2DArray *outHeight = dims.height; *outElements = dims.arrayElementCount; } - void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outElements, float* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outHeight, + float* outElements, + float* outNumberOfLevels) { auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; @@ -563,15 +734,30 @@ struct Texture2DArray *outElements = dims.arrayElementCount; *outNumberOfLevels = dims.numberOfLevels; } - - T Load(const int4& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; } - T Sample(SamplerState samplerState, const float3& loc) const { T out; texture->Sample(samplerState, &loc.x, &out, sizeof(out)); return out; } - T SampleLevel(SamplerState samplerState, const float3& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); return out; } - - ITexture* texture; + + T Load(const int4& loc) const + { + T out; + texture->Load(&loc.x, &out, sizeof(out)); + return out; + } + T Sample(SamplerState samplerState, const float3& loc) const + { + T out; + texture->Sample(samplerState, &loc.x, &out, sizeof(out)); + return out; + } + T SampleLevel(SamplerState samplerState, const float3& loc, float level) + { + T out; + texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); + return out; + } + + ITexture* texture; }; -template +template struct TextureCubeArray { void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements) @@ -581,7 +767,12 @@ struct TextureCubeArray *outHeight = dims.height; *outElements = dims.arrayElementCount; } - void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements, uint32_t* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + uint32_t* outWidth, + uint32_t* outHeight, + uint32_t* outElements, + uint32_t* outNumberOfLevels) { auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; @@ -589,7 +780,7 @@ struct TextureCubeArray *outElements = dims.arrayElementCount; *outNumberOfLevels = dims.numberOfLevels; } - + void GetDimensions(uint32_t* outWidth, float* outHeight, float* outElements) { auto dims = texture->GetDimensions(); @@ -597,7 +788,12 @@ struct TextureCubeArray *outHeight = dims.height; *outElements = dims.arrayElementCount; } - void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outElements, float* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outHeight, + float* outElements, + float* outNumberOfLevels) { auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; @@ -605,81 +801,124 @@ struct TextureCubeArray *outElements = dims.arrayElementCount; *outNumberOfLevels = dims.numberOfLevels; } - - T Sample(SamplerState samplerState, const float4& loc) const { T out; texture->Sample(samplerState, &loc.x, &out, sizeof(out)); return out; } - T SampleLevel(SamplerState samplerState, const float4& loc, float level) { T out; texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); return out; } - - ITexture* texture; + + T Sample(SamplerState samplerState, const float4& loc) const + { + T out; + texture->Sample(samplerState, &loc.x, &out, sizeof(out)); + return out; + } + T SampleLevel(SamplerState samplerState, const float4& loc, float level) + { + T out; + texture->SampleLevel(samplerState, &loc.x, level, &out, sizeof(out)); + return out; + } + + ITexture* texture; }; /* !!!!!!!!!!!!!!!!!!!!!!!!!!! RWTexture !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ struct IRWTexture : ITexture { - /// Get the reference to the element at loc. + /// Get the reference to the element at loc. virtual void* refAt(const uint32_t* loc) = 0; }; -template +template struct RWTexture1D { void GetDimensions(uint32_t* outWidth) { *outWidth = texture->GetDimensions().width; } - void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outNumberOfLevels) { auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; *outNumberOfLevels = dims.numberOfLevels; } - + void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outNumberOfLevels) + { + auto dims = texture->GetDimensions(mipLevel); + *outWidth = dims.width; + *outNumberOfLevels = dims.numberOfLevels; + } + void GetDimensions(float* outWidth) { *outWidth = texture->GetDimensions().width; } - void GetDimensions(uint32_t mipLevel, float* outWidth, float* outNumberOfLevels) { auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; *outNumberOfLevels = dims.numberOfLevels; } - - T Load(int32_t loc) const { T out; texture->Load(&loc, &out, sizeof(out)); return out; } + void GetDimensions(uint32_t mipLevel, float* outWidth, float* outNumberOfLevels) + { + auto dims = texture->GetDimensions(mipLevel); + *outWidth = dims.width; + *outNumberOfLevels = dims.numberOfLevels; + } + + T Load(int32_t loc) const + { + T out; + texture->Load(&loc, &out, sizeof(out)); + return out; + } T& operator[](uint32_t loc) { return *(T*)texture->refAt(&loc); } - IRWTexture* texture; + IRWTexture* texture; }; -template +template struct RWTexture2D { - void GetDimensions(uint32_t* outWidth, uint32_t* outHeight) - { - const auto dims = texture->GetDimensions(); - *outWidth = dims.width; - *outHeight = dims.height; + void GetDimensions(uint32_t* outWidth, uint32_t* outHeight) + { + const auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; } - void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + uint32_t* outWidth, + uint32_t* outHeight, + uint32_t* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; *outHeight = dims.height; *outNumberOfLevels = dims.numberOfLevels; } - void GetDimensions(float* outWidth, float* outHeight) - { - const auto dims = texture->GetDimensions(); - *outWidth = dims.width; - *outHeight = dims.height; + void GetDimensions(float* outWidth, float* outHeight) + { + const auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; } - void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outHeight, + float* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; *outHeight = dims.height; *outNumberOfLevels = dims.numberOfLevels; } - - T Load(const int2& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; } + + T Load(const int2& loc) const + { + T out; + texture->Load(&loc.x, &out, sizeof(out)); + return out; + } T& operator[](const uint2& loc) { return *(T*)texture->refAt(&loc.x); } IRWTexture* texture; }; -template +template struct RWTexture3D { void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outDepth) { - const auto dims = texture->GetDimensions(); - *outWidth = dims.width; - *outHeight = dims.height; + const auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; *outDepth = dims.depth; } - void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outDepth, uint32_t* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + uint32_t* outWidth, + uint32_t* outHeight, + uint32_t* outDepth, + uint32_t* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; @@ -689,12 +928,17 @@ struct RWTexture3D } void GetDimensions(float* outWidth, float* outHeight, float* outDepth) { - const auto dims = texture->GetDimensions(); - *outWidth = dims.width; - *outHeight = dims.height; + const auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; *outDepth = dims.depth; } - void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outDepth, float* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outHeight, + float* outDepth, + float* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; @@ -702,60 +946,83 @@ struct RWTexture3D *outDepth = dims.depth; *outNumberOfLevels = dims.numberOfLevels; } - - T Load(const int3& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; } + + T Load(const int3& loc) const + { + T out; + texture->Load(&loc.x, &out, sizeof(out)); + return out; + } T& operator[](const uint3& loc) { return *(T*)texture->refAt(&loc.x); } IRWTexture* texture; }; -template +template struct RWTexture1DArray { - void GetDimensions(uint32_t* outWidth, uint32_t* outElements) - { - auto dims = texture->GetDimensions(); - *outWidth = dims.width; - *outElements = dims.arrayElementCount; + void GetDimensions(uint32_t* outWidth, uint32_t* outElements) + { + auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outElements = dims.arrayElementCount; } - void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outElements, uint32_t* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + uint32_t* outWidth, + uint32_t* outElements, + uint32_t* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; *outElements = dims.arrayElementCount; *outNumberOfLevels = dims.numberOfLevels; } - void GetDimensions(float* outWidth, float* outElements) - { - auto dims = texture->GetDimensions(); - *outWidth = dims.width; - *outElements = dims.arrayElementCount; + void GetDimensions(float* outWidth, float* outElements) + { + auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outElements = dims.arrayElementCount; } - void GetDimensions(uint32_t mipLevel, float* outWidth, float* outElements, float* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outElements, + float* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; *outElements = dims.arrayElementCount; *outNumberOfLevels = dims.numberOfLevels; } - - T Load(int2 loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; } + + T Load(int2 loc) const + { + T out; + texture->Load(&loc.x, &out, sizeof(out)); + return out; + } T& operator[](uint2 loc) { return *(T*)texture->refAt(&loc.x); } IRWTexture* texture; }; -template +template struct RWTexture2DArray { void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements) { - auto dims = texture->GetDimensions(); - *outWidth = dims.width; + auto dims = texture->GetDimensions(); + *outWidth = dims.width; *outHeight = dims.height; - *outElements = dims.arrayElementCount; + *outElements = dims.arrayElementCount; } - void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements, uint32_t* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + uint32_t* outWidth, + uint32_t* outHeight, + uint32_t* outElements, + uint32_t* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; @@ -765,12 +1032,17 @@ struct RWTexture2DArray } void GetDimensions(float* outWidth, float* outHeight, float* outElements) { - auto dims = texture->GetDimensions(); - *outWidth = dims.width; + auto dims = texture->GetDimensions(); + *outWidth = dims.width; *outHeight = dims.height; - *outElements = dims.arrayElementCount; + *outElements = dims.arrayElementCount; } - void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outElements, float* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outHeight, + float* outElements, + float* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; @@ -778,8 +1050,13 @@ struct RWTexture2DArray *outElements = dims.arrayElementCount; *outNumberOfLevels = dims.numberOfLevels; } - - T Load(const int3& loc) const { T out; texture->Load(&loc.x, &out, sizeof(out)); return out; } + + T Load(const int3& loc) const + { + T out; + texture->Load(&loc.x, &out, sizeof(out)); + return out; + } T& operator[](const uint3& loc) { return *(T*)texture->refAt(&loc.x); } IRWTexture* texture; @@ -787,91 +1064,167 @@ struct RWTexture2DArray // FeedbackTexture -struct FeedbackType {}; -struct SAMPLER_FEEDBACK_MIN_MIP : FeedbackType {}; -struct SAMPLER_FEEDBACK_MIP_REGION_USED : FeedbackType {}; +struct FeedbackType +{ +}; +struct SAMPLER_FEEDBACK_MIN_MIP : FeedbackType +{ +}; +struct SAMPLER_FEEDBACK_MIP_REGION_USED : FeedbackType +{ +}; struct IFeedbackTexture { virtual TextureDimensions GetDimensions(int mipLevel = -1) = 0; - // Note here we pass the optional clamp parameter as a pointer. Passing nullptr means no clamp. - // This was preferred over having two function definitions, and having to differentiate their names - virtual void WriteSamplerFeedback(ITexture* tex, SamplerState samp, const float* location, const float* clamp = nullptr) = 0; - virtual void WriteSamplerFeedbackBias(ITexture* tex, SamplerState samp, const float* location, float bias, const float* clamp = nullptr) = 0; - virtual void WriteSamplerFeedbackGrad(ITexture* tex, SamplerState samp, const float* location, const float* ddx, const float* ddy, const float* clamp = nullptr) = 0; - - virtual void WriteSamplerFeedbackLevel(ITexture* tex, SamplerState samp, const float* location, float lod) = 0; + // Note here we pass the optional clamp parameter as a pointer. Passing nullptr means no clamp. + // This was preferred over having two function definitions, and having to differentiate their + // names + virtual void WriteSamplerFeedback( + ITexture* tex, + SamplerState samp, + const float* location, + const float* clamp = nullptr) = 0; + virtual void WriteSamplerFeedbackBias( + ITexture* tex, + SamplerState samp, + const float* location, + float bias, + const float* clamp = nullptr) = 0; + virtual void WriteSamplerFeedbackGrad( + ITexture* tex, + SamplerState samp, + const float* location, + const float* ddx, + const float* ddy, + const float* clamp = nullptr) = 0; + + virtual void WriteSamplerFeedbackLevel( + ITexture* tex, + SamplerState samp, + const float* location, + float lod) = 0; }; -template +template struct FeedbackTexture2D { - void GetDimensions(uint32_t* outWidth, uint32_t* outHeight) - { - const auto dims = texture->GetDimensions(); - *outWidth = dims.width; - *outHeight = dims.height; + void GetDimensions(uint32_t* outWidth, uint32_t* outHeight) + { + const auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; } - void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + uint32_t* outWidth, + uint32_t* outHeight, + uint32_t* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; *outHeight = dims.height; *outNumberOfLevels = dims.numberOfLevels; } - void GetDimensions(float* outWidth, float* outHeight) - { - const auto dims = texture->GetDimensions(); - *outWidth = dims.width; - *outHeight = dims.height; + void GetDimensions(float* outWidth, float* outHeight) + { + const auto dims = texture->GetDimensions(); + *outWidth = dims.width; + *outHeight = dims.height; } - void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outHeight, + float* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; *outHeight = dims.height; *outNumberOfLevels = dims.numberOfLevels; } - - template - void WriteSamplerFeedback(Texture2D tex, SamplerState samp, float2 location, float clamp) { texture->WriteSamplerFeedback(tex.texture, samp, &location.x, &clamp); } - template - void WriteSamplerFeedbackBias(Texture2D tex, SamplerState samp, float2 location, float bias, float clamp) { texture->WriteSamplerFeedbackBias(tex.texture, samp, &location.x, bias, &clamp); } + template + void WriteSamplerFeedback(Texture2D tex, SamplerState samp, float2 location, float clamp) + { + texture->WriteSamplerFeedback(tex.texture, samp, &location.x, &clamp); + } - template - void WriteSamplerFeedbackGrad(Texture2D tex, SamplerState samp, float2 location, float2 ddx, float2 ddy, float clamp) { texture->WriteSamplerFeedbackGrad(tex.texture, samp, &location.x, &ddx.x, &ddy.x, &clamp); } + template + void WriteSamplerFeedbackBias( + Texture2D tex, + SamplerState samp, + float2 location, + float bias, + float clamp) + { + texture->WriteSamplerFeedbackBias(tex.texture, samp, &location.x, bias, &clamp); + } + + template + void WriteSamplerFeedbackGrad( + Texture2D tex, + SamplerState samp, + float2 location, + float2 ddx, + float2 ddy, + float clamp) + { + texture->WriteSamplerFeedbackGrad(tex.texture, samp, &location.x, &ddx.x, &ddy.x, &clamp); + } // Level - template - void WriteSamplerFeedbackLevel(Texture2D tex, SamplerState samp, float2 location, float lod) { texture->WriteSamplerFeedbackLevel(tex.texture, samp, &location.x, lod); } - + template + void WriteSamplerFeedbackLevel(Texture2D tex, SamplerState samp, float2 location, float lod) + { + texture->WriteSamplerFeedbackLevel(tex.texture, samp, &location.x, lod); + } + // Without Clamp - template - void WriteSamplerFeedback(Texture2D tex, SamplerState samp, float2 location) { texture->WriteSamplerFeedback(tex.texture, samp, &location.x); } + template + void WriteSamplerFeedback(Texture2D tex, SamplerState samp, float2 location) + { + texture->WriteSamplerFeedback(tex.texture, samp, &location.x); + } + + template + void WriteSamplerFeedbackBias(Texture2D tex, SamplerState samp, float2 location, float bias) + { + texture->WriteSamplerFeedbackBias(tex.texture, samp, &location.x, bias); + } - template - void WriteSamplerFeedbackBias(Texture2D tex, SamplerState samp, float2 location, float bias) { texture->WriteSamplerFeedbackBias(tex.texture, samp, &location.x, bias); } + template + void WriteSamplerFeedbackGrad( + Texture2D tex, + SamplerState samp, + float2 location, + float2 ddx, + float2 ddy) + { + texture->WriteSamplerFeedbackGrad(tex.texture, samp, &location.x, &ddx.x, &ddy.x); + } - template - void WriteSamplerFeedbackGrad(Texture2D tex, SamplerState samp, float2 location, float2 ddx, float2 ddy) { texture->WriteSamplerFeedbackGrad(tex.texture, samp, &location.x, &ddx.x, &ddy.x); } - IFeedbackTexture* texture; }; -template +template struct FeedbackTexture2DArray { void GetDimensions(uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements) { - auto dims = texture->GetDimensions(); - *outWidth = dims.width; + auto dims = texture->GetDimensions(); + *outWidth = dims.width; *outHeight = dims.height; - *outElements = dims.arrayElementCount; + *outElements = dims.arrayElementCount; } - void GetDimensions(uint32_t mipLevel, uint32_t* outWidth, uint32_t* outHeight, uint32_t* outElements, uint32_t* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + uint32_t* outWidth, + uint32_t* outHeight, + uint32_t* outElements, + uint32_t* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; @@ -881,12 +1234,17 @@ struct FeedbackTexture2DArray } void GetDimensions(float* outWidth, float* outHeight, float* outElements) { - auto dims = texture->GetDimensions(); - *outWidth = dims.width; + auto dims = texture->GetDimensions(); + *outWidth = dims.width; *outHeight = dims.height; - *outElements = dims.arrayElementCount; + *outElements = dims.arrayElementCount; } - void GetDimensions(uint32_t mipLevel, float* outWidth, float* outHeight, float* outElements, float* outNumberOfLevels) + void GetDimensions( + uint32_t mipLevel, + float* outWidth, + float* outHeight, + float* outElements, + float* outNumberOfLevels) { const auto dims = texture->GetDimensions(mipLevel); *outWidth = dims.width; @@ -894,31 +1252,81 @@ struct FeedbackTexture2DArray *outElements = dims.arrayElementCount; *outNumberOfLevels = dims.numberOfLevels; } - - template - void WriteSamplerFeedback(Texture2DArray texArray, SamplerState samp, float3 location, float clamp) { texture->WriteSamplerFeedback(texArray.texture, samp, &location.x, &clamp); } - template - void WriteSamplerFeedbackBias(Texture2DArray texArray, SamplerState samp, float3 location, float bias, float clamp) { texture->WriteSamplerFeedbackBias(texArray.texture, samp, &location.x, bias, &clamp); } + template + void WriteSamplerFeedback( + Texture2DArray texArray, + SamplerState samp, + float3 location, + float clamp) + { + texture->WriteSamplerFeedback(texArray.texture, samp, &location.x, &clamp); + } + + template + void WriteSamplerFeedbackBias( + Texture2DArray texArray, + SamplerState samp, + float3 location, + float bias, + float clamp) + { + texture->WriteSamplerFeedbackBias(texArray.texture, samp, &location.x, bias, &clamp); + } - template - void WriteSamplerFeedbackGrad(Texture2DArray texArray, SamplerState samp, float3 location, float3 ddx, float3 ddy, float clamp) { texture->WriteSamplerFeedbackGrad(texArray.texture, samp, &location.x, &ddx.x, &ddy.x, &clamp); } + template + void WriteSamplerFeedbackGrad( + Texture2DArray texArray, + SamplerState samp, + float3 location, + float3 ddx, + float3 ddy, + float clamp) + { + texture + ->WriteSamplerFeedbackGrad(texArray.texture, samp, &location.x, &ddx.x, &ddy.x, &clamp); + } // Level - template - void WriteSamplerFeedbackLevel(Texture2DArray texArray, SamplerState samp, float3 location, float lod) { texture->WriteSamplerFeedbackLevel(texArray.texture, samp, &location.x, lod); } + template + void WriteSamplerFeedbackLevel( + Texture2DArray texArray, + SamplerState samp, + float3 location, + float lod) + { + texture->WriteSamplerFeedbackLevel(texArray.texture, samp, &location.x, lod); + } // Without Clamp - template - void WriteSamplerFeedback(Texture2DArray texArray, SamplerState samp, float3 location) { texture->WriteSamplerFeedback(texArray.texture, samp, &location.x); } + template + void WriteSamplerFeedback(Texture2DArray texArray, SamplerState samp, float3 location) + { + texture->WriteSamplerFeedback(texArray.texture, samp, &location.x); + } - template - void WriteSamplerFeedbackBias(Texture2DArray texArray, SamplerState samp, float3 location, float bias) { texture->WriteSamplerFeedbackBias(texArray.texture, samp, &location.x, bias); } + template + void WriteSamplerFeedbackBias( + Texture2DArray texArray, + SamplerState samp, + float3 location, + float bias) + { + texture->WriteSamplerFeedbackBias(texArray.texture, samp, &location.x, bias); + } + + template + void WriteSamplerFeedbackGrad( + Texture2DArray texArray, + SamplerState samp, + float3 location, + float3 ddx, + float3 ddy) + { + texture->WriteSamplerFeedbackGrad(texArray.texture, samp, &location.x, &ddx.x, &ddy.x); + } - template - void WriteSamplerFeedbackGrad(Texture2DArray texArray, SamplerState samp, float3 location, float3 ddx, float3 ddy) { texture->WriteSamplerFeedbackGrad(texArray.texture, samp, &location.x, &ddx.x, &ddy.x); } - IFeedbackTexture* texture; }; @@ -933,20 +1341,24 @@ struct ComputeThreadVaryingInput struct ComputeVaryingInput { - uint3 startGroupID; ///< start groupID - uint3 endGroupID; ///< Non inclusive end groupID + uint3 startGroupID; ///< start groupID + uint3 endGroupID; ///< Non inclusive end groupID }; -// The uniformEntryPointParams and uniformState must be set to structures that match layout that the kernel expects. -// This can be determined via reflection for example. +// The uniformEntryPointParams and uniformState must be set to structures that match layout that the +// kernel expects. This can be determined via reflection for example. -typedef void(*ComputeThreadFunc)(ComputeThreadVaryingInput* varyingInput, void* uniformEntryPointParams, void* uniformState); -typedef void(*ComputeFunc)(ComputeVaryingInput* varyingInput, void* uniformEntryPointParams, void* uniformState); +typedef void (*ComputeThreadFunc)( + ComputeThreadVaryingInput* varyingInput, + void* uniformEntryPointParams, + void* uniformState); +typedef void (*ComputeFunc)( + ComputeVaryingInput* varyingInput, + void* uniformEntryPointParams, + void* uniformState); #ifdef SLANG_PRELUDE_NAMESPACE } #endif #endif - - diff --git a/prelude/slang-cuda-prelude.h b/prelude/slang-cuda-prelude.h index e0335f08a..9ac903955 100644 --- a/prelude/slang-cuda-prelude.h +++ b/prelude/slang-cuda-prelude.h @@ -15,51 +15,53 @@ #endif -// Define SLANG_CUDA_ENABLE_HALF to use the cuda_fp16 include to add half support. +// Define SLANG_CUDA_ENABLE_HALF to use the cuda_fp16 include to add half support. // For this to work NVRTC needs to have the path to the CUDA SDK. // -// As it stands the includes paths defined for Slang are passed down to NVRTC. Similarly defines defined for the Slang compile -// are passed down. +// As it stands the includes paths defined for Slang are passed down to NVRTC. Similarly defines +// defined for the Slang compile are passed down. #ifdef SLANG_CUDA_ENABLE_HALF -// We don't want half2 operators, because it will implement comparison operators that return a bool(!). We want to generate -// those functions. Doing so means that we will have to define all the other half2 operators. -# define __CUDA_NO_HALF2_OPERATORS__ -# include +// We don't want half2 operators, because it will implement comparison operators that return a +// bool(!). We want to generate those functions. Doing so means that we will have to define all +// the other half2 operators. +#define __CUDA_NO_HALF2_OPERATORS__ +#include #endif #ifdef SLANG_CUDA_ENABLE_OPTIX #include #endif -// Define slang offsetof implementation +// Define slang offsetof implementation #ifndef SLANG_OFFSET_OF -# define SLANG_OFFSET_OF(type, member) (size_t)((char*)&(((type *)0)->member) - (char*)0) +#define SLANG_OFFSET_OF(type, member) (size_t)((char*)&(((type*)0)->member) - (char*)0) #endif #ifndef SLANG_ALIGN_OF -# define SLANG_ALIGN_OF(type) __alignof__(type) +#define SLANG_ALIGN_OF(type) __alignof__(type) #endif // Must be large enough to cause overflow and therefore infinity #ifndef SLANG_INFINITY -# define SLANG_INFINITY ((float)(1e+300 * 1e+300)) +#define SLANG_INFINITY ((float)(1e+300 * 1e+300)) #endif // For now we'll disable any asserts in this prelude -#define SLANG_PRELUDE_ASSERT(x) +#define SLANG_PRELUDE_ASSERT(x) -#ifndef SLANG_CUDA_WARP_SIZE -# define SLANG_CUDA_WARP_SIZE 32 +#ifndef SLANG_CUDA_WARP_SIZE +#define SLANG_CUDA_WARP_SIZE 32 #endif -#define SLANG_CUDA_WARP_MASK (SLANG_CUDA_WARP_SIZE - 1) // Used for masking threadIdx.x to the warp lane index +#define SLANG_CUDA_WARP_MASK \ + (SLANG_CUDA_WARP_SIZE - 1) // Used for masking threadIdx.x to the warp lane index #define SLANG_CUDA_WARP_BITMASK (~int(0)) // #define SLANG_FORCE_INLINE inline -#define SLANG_CUDA_CALL __device__ +#define SLANG_CUDA_CALL __device__ #define SLANG_FORCE_INLINE inline #define SLANG_INLINE inline @@ -71,54 +73,63 @@ // Asserts for bounds checking. // It is assumed index/count are unsigned types. -#define SLANG_BOUND_ASSERT(index, count) SLANG_PRELUDE_ASSERT(index < count); -#define SLANG_BOUND_ASSERT_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_PRELUDE_ASSERT(index <= (sizeInBytes - elemSize) && (index & 3) == 0); +#define SLANG_BOUND_ASSERT(index, count) SLANG_PRELUDE_ASSERT(index < count); +#define SLANG_BOUND_ASSERT_BYTE_ADDRESS(index, elemSize, sizeInBytes) \ + SLANG_PRELUDE_ASSERT(index <= (sizeInBytes - elemSize) && (index & 3) == 0); // Macros to zero index if an access is out of range -#define SLANG_BOUND_ZERO_INDEX(index, count) index = (index < count) ? index : 0; -#define SLANG_BOUND_ZERO_INDEX_BYTE_ADDRESS(index, elemSize, sizeInBytes) index = (index <= (sizeInBytes - elemSize)) ? index : 0; - -// The 'FIX' macro define how the index is fixed. The default is to do nothing. If SLANG_ENABLE_BOUND_ZERO_INDEX -// the fix macro will zero the index, if out of range -#ifdef SLANG_ENABLE_BOUND_ZERO_INDEX -# define SLANG_BOUND_FIX(index, count) SLANG_BOUND_ZERO_INDEX(index, count) -# define SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_BOUND_ZERO_INDEX_BYTE_ADDRESS(index, elemSize, sizeInBytes) -# define SLANG_BOUND_FIX_FIXED_ARRAY(index, count) SLANG_BOUND_ZERO_INDEX(index, count) SLANG_BOUND_ZERO_INDEX(index, count) +#define SLANG_BOUND_ZERO_INDEX(index, count) index = (index < count) ? index : 0; +#define SLANG_BOUND_ZERO_INDEX_BYTE_ADDRESS(index, elemSize, sizeInBytes) \ + index = (index <= (sizeInBytes - elemSize)) ? index : 0; + +// The 'FIX' macro define how the index is fixed. The default is to do nothing. If +// SLANG_ENABLE_BOUND_ZERO_INDEX the fix macro will zero the index, if out of range +#ifdef SLANG_ENABLE_BOUND_ZERO_INDEX +#define SLANG_BOUND_FIX(index, count) SLANG_BOUND_ZERO_INDEX(index, count) +#define SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) \ + SLANG_BOUND_ZERO_INDEX_BYTE_ADDRESS(index, elemSize, sizeInBytes) +#define SLANG_BOUND_FIX_FIXED_ARRAY(index, count) \ + SLANG_BOUND_ZERO_INDEX(index, count) SLANG_BOUND_ZERO_INDEX(index, count) #else -# define SLANG_BOUND_FIX(index, count) -# define SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) -# define SLANG_BOUND_FIX_FIXED_ARRAY(index, count) +#define SLANG_BOUND_FIX(index, count) +#define SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) +#define SLANG_BOUND_FIX_FIXED_ARRAY(index, count) #endif #ifndef SLANG_BOUND_CHECK -# define SLANG_BOUND_CHECK(index, count) SLANG_BOUND_ASSERT(index, count) SLANG_BOUND_FIX(index, count) +#define SLANG_BOUND_CHECK(index, count) \ + SLANG_BOUND_ASSERT(index, count) SLANG_BOUND_FIX(index, count) #endif #ifndef SLANG_BOUND_CHECK_BYTE_ADDRESS -# define SLANG_BOUND_CHECK_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_BOUND_ASSERT_BYTE_ADDRESS(index, elemSize, sizeInBytes) SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) +#define SLANG_BOUND_CHECK_BYTE_ADDRESS(index, elemSize, sizeInBytes) \ + SLANG_BOUND_ASSERT_BYTE_ADDRESS(index, elemSize, sizeInBytes) \ + SLANG_BOUND_FIX_BYTE_ADDRESS(index, elemSize, sizeInBytes) #endif #ifndef SLANG_BOUND_CHECK_FIXED_ARRAY -# define SLANG_BOUND_CHECK_FIXED_ARRAY(index, count) SLANG_BOUND_ASSERT(index, count) SLANG_BOUND_FIX_FIXED_ARRAY(index, count) +#define SLANG_BOUND_CHECK_FIXED_ARRAY(index, count) \ + SLANG_BOUND_ASSERT(index, count) SLANG_BOUND_FIX_FIXED_ARRAY(index, count) #endif - // This macro handles how out-of-range surface coordinates are handled; - // I can equal - // cudaBoundaryModeClamp, in which case out-of-range coordinates are clamped to the valid range - // cudaBoundaryModeZero, in which case out-of-range reads return zero and out-of-range writes are ignored - // cudaBoundaryModeTrap, in which case out-of-range accesses cause the kernel execution to fail. - +// This macro handles how out-of-range surface coordinates are handled; +// I can equal +// cudaBoundaryModeClamp, in which case out-of-range coordinates are clamped to the valid range +// cudaBoundaryModeZero, in which case out-of-range reads return zero and out-of-range writes are +// ignored cudaBoundaryModeTrap, in which case out-of-range accesses cause the kernel execution to +// fail. + #ifndef SLANG_CUDA_BOUNDARY_MODE -# define SLANG_CUDA_BOUNDARY_MODE cudaBoundaryModeZero +#define SLANG_CUDA_BOUNDARY_MODE cudaBoundaryModeZero // Can be one of SLANG_CUDA_PTX_BOUNDARY_MODE. Only applies *PTX* emitted CUDA operations // which currently is just RWTextureRW format writes -// +// // .trap causes an execution trap on out-of-bounds addresses // .clamp stores data at the nearest surface location (sized appropriately) -// .zero drops stores to out-of-bounds addresses +// .zero drops stores to out-of-bounds addresses -# define SLANG_PTX_BOUNDARY_MODE "zero" +#define SLANG_PTX_BOUNDARY_MODE "zero" #endif struct TypeInfo @@ -126,51 +137,67 @@ struct TypeInfo size_t typeSize; }; -template +template struct FixedArray { - SLANG_CUDA_CALL const T& operator[](size_t index) const { SLANG_BOUND_CHECK_FIXED_ARRAY(index, SIZE); return m_data[index]; } - SLANG_CUDA_CALL T& operator[](size_t index) { SLANG_BOUND_CHECK_FIXED_ARRAY(index, SIZE); return m_data[index]; } - + SLANG_CUDA_CALL const T& operator[](size_t index) const + { + SLANG_BOUND_CHECK_FIXED_ARRAY(index, SIZE); + return m_data[index]; + } + SLANG_CUDA_CALL T& operator[](size_t index) + { + SLANG_BOUND_CHECK_FIXED_ARRAY(index, SIZE); + return m_data[index]; + } + T m_data[SIZE]; }; -// An array that has no specified size, becomes a 'Array'. This stores the size so it can potentially -// do bounds checking. -template +// An array that has no specified size, becomes a 'Array'. This stores the size so it can +// potentially do bounds checking. +template struct Array { - SLANG_CUDA_CALL const T& operator[](size_t index) const { SLANG_BOUND_CHECK(index, count); return data[index]; } - SLANG_CUDA_CALL T& operator[](size_t index) { SLANG_BOUND_CHECK(index, count); return data[index]; } - + SLANG_CUDA_CALL const T& operator[](size_t index) const + { + SLANG_BOUND_CHECK(index, count); + return data[index]; + } + SLANG_CUDA_CALL T& operator[](size_t index) + { + SLANG_BOUND_CHECK(index, count); + return data[index]; + } + T* data; size_t count; }; // Typically defined in cuda.h, but we can't ship/rely on that, so just define here -typedef unsigned long long CUtexObject; -typedef unsigned long long CUsurfObject; +typedef unsigned long long CUtexObject; +typedef unsigned long long CUsurfObject; -// On CUDA sampler state is actually bound up with the texture object. We have a SamplerState type, -// backed as a pointer, to simplify code generation, with the downside that such a binding will take up -// uniform space, even though it will have no effect. +// On CUDA sampler state is actually bound up with the texture object. We have a SamplerState type, +// backed as a pointer, to simplify code generation, with the downside that such a binding will take +// up uniform space, even though it will have no effect. // TODO(JS): Consider ways to strip use of variables of this type so have no binding, struct SamplerStateUnused; typedef SamplerStateUnused* SamplerState; // TODO(JS): Not clear yet if this can be handled on CUDA, by just ignoring. -// For now, just map to the index type. +// For now, just map to the index type. typedef size_t NonUniformResourceIndex; // Code generator will generate the specific type -template +template struct Matrix; typedef int1 bool1; typedef int2 bool2; typedef int3 bool3; -typedef int4 bool4; +typedef int4 bool4; #if SLANG_CUDA_RTC @@ -193,7 +220,7 @@ typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; -union Union32 +union Union32 { uint32_t u; int32_t i; @@ -225,16 +252,37 @@ SLANG_FORCE_INLINE SLANG_CUDA_CALL double _slang_fmod(double x, double y) #if SLANG_CUDA_ENABLE_HALF // Add the other vector half types -struct __half1 { __half x; }; -struct __align__(4) __half3 { __half x, y, z; }; -struct __align__(4) __half4 { __half x, y, z, w; }; +struct __half1 +{ + __half x; +}; +struct __align__(4) __half3 +{ + __half x, y, z; +}; +struct __align__(4) __half4 +{ + __half x, y, z, w; +}; #endif -#define SLANG_VECTOR_GET_ELEMENT(T) \ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T _slang_vector_get_element(T##1 x, int index) { return ((T*)(&x))[index]; }\ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T _slang_vector_get_element(T##2 x, int index) { return ((T*)(&x))[index]; }\ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T _slang_vector_get_element(T##3 x, int index) { return ((T*)(&x))[index]; }\ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T _slang_vector_get_element(T##4 x, int index) { return ((T*)(&x))[index]; } +#define SLANG_VECTOR_GET_ELEMENT(T) \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T _slang_vector_get_element(T##1 x, int index) \ + { \ + return ((T*)(&x))[index]; \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T _slang_vector_get_element(T##2 x, int index) \ + { \ + return ((T*)(&x))[index]; \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T _slang_vector_get_element(T##3 x, int index) \ + { \ + return ((T*)(&x))[index]; \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T _slang_vector_get_element(T##4 x, int index) \ + { \ + return ((T*)(&x))[index]; \ + } SLANG_VECTOR_GET_ELEMENT(int) SLANG_VECTOR_GET_ELEMENT(uint) SLANG_VECTOR_GET_ELEMENT(short) @@ -246,11 +294,23 @@ SLANG_VECTOR_GET_ELEMENT(ulonglong) SLANG_VECTOR_GET_ELEMENT(float) SLANG_VECTOR_GET_ELEMENT(double) -#define SLANG_VECTOR_GET_ELEMENT_PTR(T) \ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T* _slang_vector_get_element_ptr(T##1* x, int index) { return ((T*)(x)) + index; }\ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T* _slang_vector_get_element_ptr(T##2* x, int index) { return ((T*)(x)) + index; }\ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T* _slang_vector_get_element_ptr(T##3* x, int index) { return ((T*)(x)) + index; }\ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T* _slang_vector_get_element_ptr(T##4* x, int index) { return ((T*)(x)) + index; } +#define SLANG_VECTOR_GET_ELEMENT_PTR(T) \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T* _slang_vector_get_element_ptr(T##1 * x, int index) \ + { \ + return ((T*)(x)) + index; \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T* _slang_vector_get_element_ptr(T##2 * x, int index) \ + { \ + return ((T*)(x)) + index; \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T* _slang_vector_get_element_ptr(T##3 * x, int index) \ + { \ + return ((T*)(x)) + index; \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T* _slang_vector_get_element_ptr(T##4 * x, int index) \ + { \ + return ((T*)(x)) + index; \ + } SLANG_VECTOR_GET_ELEMENT_PTR(int) SLANG_VECTOR_GET_ELEMENT_PTR(uint) SLANG_VECTOR_GET_ELEMENT_PTR(short) @@ -267,57 +327,60 @@ SLANG_VECTOR_GET_ELEMENT(__half) SLANG_VECTOR_GET_ELEMENT_PTR(__half) #endif -#define SLANG_CUDA_VECTOR_BINARY_OP(T, n, op) \ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T##n operator op(T##n thisVal, T##n other) \ - { \ - T##n result;\ - for (int i = 0; i < n; i++) \ - *_slang_vector_get_element_ptr(&result, i) = _slang_vector_get_element(thisVal,i) op _slang_vector_get_element(other,i); \ - return result;\ +#define SLANG_CUDA_VECTOR_BINARY_OP(T, n, op) \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##n operator op(T##n thisVal, T##n other) \ + { \ + T##n result; \ + for (int i = 0; i < n; i++) \ + *_slang_vector_get_element_ptr(&result, i) = \ + _slang_vector_get_element(thisVal, i) op _slang_vector_get_element(other, i); \ + return result; \ } -#define SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, op) \ +#define SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, op) \ SLANG_FORCE_INLINE SLANG_CUDA_CALL bool##n operator op(T##n thisVal, T##n other) \ - { \ - bool##n result;\ - for (int i = 0; i < n; i++) \ - *_slang_vector_get_element_ptr(&result, i) = (int)(_slang_vector_get_element(thisVal,i) op _slang_vector_get_element(other,i)); \ - return result;\ - } -#define SLANG_CUDA_VECTOR_UNARY_OP(T, n, op) \ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T##n operator op(T##n thisVal) \ - { \ - T##n result;\ - for (int i = 0; i < n; i++) \ - *_slang_vector_get_element_ptr(&result, i) = op _slang_vector_get_element(thisVal,i); \ - return result;\ - } - -#define SLANG_CUDA_VECTOR_INT_OP(T, n) \ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, +)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, -)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, *)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, /)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, %)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, ^)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, &)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, |)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, &&)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, ||)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, >>)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, <<)\ - SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, >)\ - SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, <)\ - SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, >=)\ - SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, <=)\ - SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, ==)\ - SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, !=)\ - SLANG_CUDA_VECTOR_UNARY_OP(T, n, !)\ - SLANG_CUDA_VECTOR_UNARY_OP(T, n, -)\ + { \ + bool##n result; \ + for (int i = 0; i < n; i++) \ + *_slang_vector_get_element_ptr(&result, i) = \ + (int)(_slang_vector_get_element(thisVal, i) \ + op _slang_vector_get_element(other, i)); \ + return result; \ + } +#define SLANG_CUDA_VECTOR_UNARY_OP(T, n, op) \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##n operator op(T##n thisVal) \ + { \ + T##n result; \ + for (int i = 0; i < n; i++) \ + *_slang_vector_get_element_ptr(&result, i) = op _slang_vector_get_element(thisVal, i); \ + return result; \ + } + +#define SLANG_CUDA_VECTOR_INT_OP(T, n) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, +) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, -) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, *) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, /) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, %) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, ^) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, &) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, |) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, &&) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, ||) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, >>) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, <<) \ + SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, >) \ + SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, <) \ + SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, >=) \ + SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, <=) \ + SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, ==) \ + SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, !=) \ + SLANG_CUDA_VECTOR_UNARY_OP(T, n, !) \ + SLANG_CUDA_VECTOR_UNARY_OP(T, n, -) \ SLANG_CUDA_VECTOR_UNARY_OP(T, n, ~) #define SLANG_CUDA_VECTOR_INT_OPS(T) \ - SLANG_CUDA_VECTOR_INT_OP(T, 2) \ - SLANG_CUDA_VECTOR_INT_OP(T, 3) \ + SLANG_CUDA_VECTOR_INT_OP(T, 2) \ + SLANG_CUDA_VECTOR_INT_OP(T, 3) \ SLANG_CUDA_VECTOR_INT_OP(T, 4) SLANG_CUDA_VECTOR_INT_OPS(int) @@ -329,23 +392,23 @@ SLANG_CUDA_VECTOR_INT_OPS(uchar) SLANG_CUDA_VECTOR_INT_OPS(longlong) SLANG_CUDA_VECTOR_INT_OPS(ulonglong) -#define SLANG_CUDA_VECTOR_FLOAT_OP(T, n) \ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, +)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, -)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, *)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, /)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, &&)\ - SLANG_CUDA_VECTOR_BINARY_OP(T, n, ||)\ - SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, >)\ - SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, <)\ - SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, >=)\ - SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, <=)\ - SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, ==)\ - SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, !=)\ +#define SLANG_CUDA_VECTOR_FLOAT_OP(T, n) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, +) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, -) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, *) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, /) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, &&) \ + SLANG_CUDA_VECTOR_BINARY_OP(T, n, ||) \ + SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, >) \ + SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, <) \ + SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, >=) \ + SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, <=) \ + SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, ==) \ + SLANG_CUDA_VECTOR_BINARY_COMPARE_OP(T, n, !=) \ SLANG_CUDA_VECTOR_UNARY_OP(T, n, -) #define SLANG_CUDA_VECTOR_FLOAT_OPS(T) \ - SLANG_CUDA_VECTOR_FLOAT_OP(T, 2) \ - SLANG_CUDA_VECTOR_FLOAT_OP(T, 3) \ + SLANG_CUDA_VECTOR_FLOAT_OP(T, 2) \ + SLANG_CUDA_VECTOR_FLOAT_OP(T, 3) \ SLANG_CUDA_VECTOR_FLOAT_OP(T, 4) SLANG_CUDA_VECTOR_FLOAT_OPS(float) @@ -353,27 +416,38 @@ SLANG_CUDA_VECTOR_FLOAT_OPS(double) #if SLANG_CUDA_ENABLE_HALF SLANG_CUDA_VECTOR_FLOAT_OPS(__half) #endif -#define SLANG_CUDA_FLOAT_VECTOR_MOD_IMPL(T, n)\ +#define SLANG_CUDA_FLOAT_VECTOR_MOD_IMPL(T, n) \ SLANG_FORCE_INLINE SLANG_CUDA_CALL T##n operator%(const T##n& left, const T##n& right) \ - {\ - T##n result;\ - for (int i = 0; i < n; i++) \ - *_slang_vector_get_element_ptr(&result, i) = _slang_fmod(_slang_vector_get_element(left,i), _slang_vector_get_element(right,i)); \ - return result;\ - } -#define SLANG_CUDA_FLOAT_VECTOR_MOD(T) \ - SLANG_CUDA_FLOAT_VECTOR_MOD_IMPL(T, 2)\ - SLANG_CUDA_FLOAT_VECTOR_MOD_IMPL(T, 3)\ + { \ + T##n result; \ + for (int i = 0; i < n; i++) \ + *_slang_vector_get_element_ptr(&result, i) = _slang_fmod( \ + _slang_vector_get_element(left, i), \ + _slang_vector_get_element(right, i)); \ + return result; \ + } +#define SLANG_CUDA_FLOAT_VECTOR_MOD(T) \ + SLANG_CUDA_FLOAT_VECTOR_MOD_IMPL(T, 2) \ + SLANG_CUDA_FLOAT_VECTOR_MOD_IMPL(T, 3) \ SLANG_CUDA_FLOAT_VECTOR_MOD_IMPL(T, 4) SLANG_CUDA_FLOAT_VECTOR_MOD(float) SLANG_CUDA_FLOAT_VECTOR_MOD(double) #if SLANG_CUDA_RTC || SLANG_CUDA_ENABLE_HALF -#define SLANG_MAKE_VECTOR(T) \ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T##2 make_##T##2(T x, T y) { return T##2{x, y}; }\ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T##3 make_##T##3(T x, T y, T z) { return T##3{ x, y, z }; }\ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T##4 make_##T##4(T x, T y, T z, T w) { return T##4{ x, y, z, w }; } +#define SLANG_MAKE_VECTOR(T) \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##2 make_##T##2(T x, T y) \ + { \ + return T##2 {x, y}; \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##3 make_##T##3(T x, T y, T z) \ + { \ + return T##3 {x, y, z}; \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##4 make_##T##4(T x, T y, T z, T w) \ + { \ + return T##4 {x, y, z, w}; \ + } #endif #if SLANG_CUDA_RTC @@ -393,25 +467,67 @@ SLANG_MAKE_VECTOR(ulonglong) SLANG_MAKE_VECTOR(__half) #endif -SLANG_FORCE_INLINE SLANG_CUDA_CALL bool1 make_bool1(bool x) { return bool1{ x }; } -SLANG_FORCE_INLINE SLANG_CUDA_CALL bool2 make_bool2(bool x, bool y) { return bool2{ x, y }; } -SLANG_FORCE_INLINE SLANG_CUDA_CALL bool3 make_bool3(bool x, bool y, bool z) { return bool3{ x, y, z }; } -SLANG_FORCE_INLINE SLANG_CUDA_CALL bool4 make_bool4(bool x, bool y, bool z, bool w) { return bool4{ x, y, z, w }; } -SLANG_FORCE_INLINE SLANG_CUDA_CALL bool2 make_bool2(bool x) { return bool2{ x, x }; } -SLANG_FORCE_INLINE SLANG_CUDA_CALL bool3 make_bool3(bool x) { return bool3{ x, x, x }; } -SLANG_FORCE_INLINE SLANG_CUDA_CALL bool4 make_bool4(bool x) { return bool4{ x, x, x, x }; } +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool1 make_bool1(bool x) +{ + return bool1{x}; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool2 make_bool2(bool x, bool y) +{ + return bool2{x, y}; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool3 make_bool3(bool x, bool y, bool z) +{ + return bool3{x, y, z}; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool4 make_bool4(bool x, bool y, bool z, bool w) +{ + return bool4{x, y, z, w}; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool2 make_bool2(bool x) +{ + return bool2{x, x}; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool3 make_bool3(bool x) +{ + return bool3{x, x, x}; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool4 make_bool4(bool x) +{ + return bool4{x, x, x, x}; +} #if SLANG_CUDA_RTC -#define SLANG_MAKE_VECTOR_FROM_SCALAR(T) \ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T##1 make_##T##1(T x) { return T##1{x}; }\ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T##2 make_##T##2(T x) { return make_##T##2(x, x); }\ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T##3 make_##T##3(T x) { return make_##T##3(x, x, x); }\ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T##4 make_##T##4(T x) { return make_##T##4(x, x, x, x); } +#define SLANG_MAKE_VECTOR_FROM_SCALAR(T) \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##1 make_##T##1(T x) \ + { \ + return T##1 {x}; \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##2 make_##T##2(T x) \ + { \ + return make_##T##2(x, x); \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##3 make_##T##3(T x) \ + { \ + return make_##T##3(x, x, x); \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##4 make_##T##4(T x) \ + { \ + return make_##T##4(x, x, x, x); \ + } #else -#define SLANG_MAKE_VECTOR_FROM_SCALAR(T) \ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T##2 make_##T##2(T x) { return make_##T##2(x, x); }\ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T##3 make_##T##3(T x) { return make_##T##3(x, x, x); }\ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T##4 make_##T##4(T x) { return make_##T##4(x, x, x, x); } +#define SLANG_MAKE_VECTOR_FROM_SCALAR(T) \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##2 make_##T##2(T x) \ + { \ + return make_##T##2(x, x); \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##3 make_##T##3(T x) \ + { \ + return make_##T##3(x, x, x); \ + } \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##4 make_##T##4(T x) \ + { \ + return make_##T##4(x, x, x, x); \ + } #endif SLANG_MAKE_VECTOR_FROM_SCALAR(int) SLANG_MAKE_VECTOR_FROM_SCALAR(uint) @@ -426,18 +542,22 @@ SLANG_MAKE_VECTOR_FROM_SCALAR(double) #if SLANG_CUDA_ENABLE_HALF SLANG_MAKE_VECTOR_FROM_SCALAR(__half) #if !SLANG_CUDA_RTC -SLANG_FORCE_INLINE SLANG_CUDA_CALL __half1 make___half1(__half x) { return __half1{x}; } +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half1 make___half1(__half x) +{ + return __half1{x}; +} #endif #endif -#define SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(Fn,T,N) \ - SLANG_FORCE_INLINE SLANG_CUDA_CALL T##N Fn(T##N* address, T##N val) \ - {\ - T##N result; \ - for (int i = 0; i < N; i++) \ - *_slang_vector_get_element_ptr(&result, i) = Fn(_slang_vector_get_element_ptr(address, i), _slang_vector_get_element(val, i)); \ - return result; \ - }\ +#define SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(Fn, T, N) \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T##N Fn(T##N* address, T##N val) \ + { \ + T##N result; \ + for (int i = 0; i < N; i++) \ + *_slang_vector_get_element_ptr(&result, i) = \ + Fn(_slang_vector_get_element_ptr(address, i), _slang_vector_get_element(val, i)); \ + return result; \ + } #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 900 SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, float, 2) @@ -455,19 +575,24 @@ SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, ulonglong, 3) SLANG_CUDA_VECTOR_ATOMIC_BINARY_IMPL(atomicAdd, ulonglong, 4) template -struct GetVectorTypeImpl {}; - -#define GET_VECTOR_TYPE_IMPL(T, n)\ -template<>\ -struct GetVectorTypeImpl\ -{\ - typedef T##n type;\ - static SLANG_FORCE_INLINE SLANG_CUDA_CALL T##n fromScalar(T v) { return make_##T##n(v); } \ +struct GetVectorTypeImpl +{ }; -#define GET_VECTOR_TYPE_IMPL_N(T)\ - GET_VECTOR_TYPE_IMPL(T, 1)\ - GET_VECTOR_TYPE_IMPL(T, 2)\ - GET_VECTOR_TYPE_IMPL(T, 3)\ + +#define GET_VECTOR_TYPE_IMPL(T, n) \ + template<> \ + struct GetVectorTypeImpl \ + { \ + typedef T##n type; \ + static SLANG_FORCE_INLINE SLANG_CUDA_CALL T##n fromScalar(T v) \ + { \ + return make_##T##n(v); \ + } \ + }; +#define GET_VECTOR_TYPE_IMPL_N(T) \ + GET_VECTOR_TYPE_IMPL(T, 1) \ + GET_VECTOR_TYPE_IMPL(T, 2) \ + GET_VECTOR_TYPE_IMPL(T, 3) \ GET_VECTOR_TYPE_IMPL(T, 4) GET_VECTOR_TYPE_IMPL_N(int) @@ -500,11 +625,14 @@ SLANG_FORCE_INLINE SLANG_CUDA_CALL Vector _slang_vector_reshape(const Vect return result; } -template +template struct Matrix { Vector rows[ROWS]; - SLANG_FORCE_INLINE SLANG_CUDA_CALL Vector& operator[](size_t index) { return rows[index]; } + SLANG_FORCE_INLINE SLANG_CUDA_CALL Vector& operator[](size_t index) + { + return rows[index]; + } }; @@ -515,7 +643,6 @@ SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(T scalar) for (int i = 0; i < ROWS; i++) result.rows[i] = GetVectorTypeImpl::fromScalar(scalar); return result; - } template @@ -527,7 +654,9 @@ SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(const Vector } template -SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(const Vector& row0, const Vector& row1) +SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix( + const Vector& row0, + const Vector& row1) { Matrix result; result.rows[0] = row0; @@ -536,7 +665,10 @@ SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(const Vector } template -SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(const Vector& row0, const Vector& row1, const Vector& row2) +SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix( + const Vector& row0, + const Vector& row1, + const Vector& row2) { Matrix result; result.rows[0] = row0; @@ -546,7 +678,11 @@ SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(const Vector } template -SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(const Vector& row0, const Vector& row1, const Vector& row2, const Vector& row3) +SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix( + const Vector& row0, + const Vector& row1, + const Vector& row2, + const Vector& row3) { Matrix result; result.rows[0] = row0; @@ -557,16 +693,20 @@ SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(const Vector } template -SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(const Matrix& other) +SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix( + const Matrix& other) { Matrix result; int minRow = ROWS; int minCol = COLS; - if (minRow > otherRow) minRow = otherRow; - if (minCol > otherCol) minCol = otherCol; + if (minRow > otherRow) + minRow = otherRow; + if (minCol > otherCol) + minCol = otherCol; for (int i = 0; i < minRow; i++) for (int j = 0; j < minCol; j++) - *_slang_vector_get_element_ptr(result.rows + i, j) = (T)_slang_vector_get_element(other.rows[i], j); + *_slang_vector_get_element_ptr(result.rows + i, j) = + (T)_slang_vector_get_element(other.rows[i], j); return result; } @@ -574,129 +714,238 @@ template SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(T v0, T v1, T v2, T v3) { Matrix rs; - rs.rows[0].x = v0; rs.rows[0].y = v1; - rs.rows[1].x = v2; rs.rows[1].y = v3; + rs.rows[0].x = v0; + rs.rows[0].y = v1; + rs.rows[1].x = v2; + rs.rows[1].y = v3; return rs; } template -SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(T v0, T v1, T v2, T v3, T v4, T v5) +SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix( + T v0, + T v1, + T v2, + T v3, + T v4, + T v5) { Matrix rs; if (COLS == 3) { - rs.rows[0].x = v0; rs.rows[0].y = v1; rs.rows[0].z = v2; - rs.rows[1].x = v3; rs.rows[1].y = v4; rs.rows[1].z = v5; + rs.rows[0].x = v0; + rs.rows[0].y = v1; + rs.rows[0].z = v2; + rs.rows[1].x = v3; + rs.rows[1].y = v4; + rs.rows[1].z = v5; } else { - rs.rows[0].x = v0; rs.rows[0].y = v1; - rs.rows[1].x = v2; rs.rows[1].y = v3; - rs.rows[2].x = v4; rs.rows[2].y = v5; + rs.rows[0].x = v0; + rs.rows[0].y = v1; + rs.rows[1].x = v2; + rs.rows[1].y = v3; + rs.rows[2].x = v4; + rs.rows[2].y = v5; } return rs; - } template -SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7) +SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix( + T v0, + T v1, + T v2, + T v3, + T v4, + T v5, + T v6, + T v7) { Matrix rs; if (COLS == 4) { - rs.rows[0].x = v0; rs.rows[0].y = v1; rs.rows[0].z = v2; rs.rows[0].w = v3; - rs.rows[1].x = v4; rs.rows[1].y = v5; rs.rows[1].z = v6; rs.rows[1].w = v7; + rs.rows[0].x = v0; + rs.rows[0].y = v1; + rs.rows[0].z = v2; + rs.rows[0].w = v3; + rs.rows[1].x = v4; + rs.rows[1].y = v5; + rs.rows[1].z = v6; + rs.rows[1].w = v7; } else { - rs.rows[0].x = v0; rs.rows[0].y = v1; - rs.rows[1].x = v2; rs.rows[1].y = v3; - rs.rows[2].x = v4; rs.rows[2].y = v5; - rs.rows[3].x = v6; rs.rows[3].y = v7; + rs.rows[0].x = v0; + rs.rows[0].y = v1; + rs.rows[1].x = v2; + rs.rows[1].y = v3; + rs.rows[2].x = v4; + rs.rows[2].y = v5; + rs.rows[3].x = v6; + rs.rows[3].y = v7; } return rs; } template -SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8) +SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix( + T v0, + T v1, + T v2, + T v3, + T v4, + T v5, + T v6, + T v7, + T v8) { Matrix rs; - rs.rows[0].x = v0; rs.rows[0].y = v1; rs.rows[0].z = v2; - rs.rows[1].x = v3; rs.rows[1].y = v4; rs.rows[1].z = v5; - rs.rows[2].x = v6; rs.rows[2].y = v7; rs.rows[2].z = v8; + rs.rows[0].x = v0; + rs.rows[0].y = v1; + rs.rows[0].z = v2; + rs.rows[1].x = v3; + rs.rows[1].y = v4; + rs.rows[1].z = v5; + rs.rows[2].x = v6; + rs.rows[2].y = v7; + rs.rows[2].z = v8; return rs; } template -SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11) +SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix( + T v0, + T v1, + T v2, + T v3, + T v4, + T v5, + T v6, + T v7, + T v8, + T v9, + T v10, + T v11) { Matrix rs; if (COLS == 4) { - rs.rows[0].x = v0; rs.rows[0].y = v1; rs.rows[0].z = v2; rs.rows[0].w = v3; - rs.rows[1].x = v4; rs.rows[1].y = v5; rs.rows[1].z = v6; rs.rows[1].w = v7; - rs.rows[2].x = v8; rs.rows[2].y = v9; rs.rows[2].z = v10; rs.rows[2].w = v11; + rs.rows[0].x = v0; + rs.rows[0].y = v1; + rs.rows[0].z = v2; + rs.rows[0].w = v3; + rs.rows[1].x = v4; + rs.rows[1].y = v5; + rs.rows[1].z = v6; + rs.rows[1].w = v7; + rs.rows[2].x = v8; + rs.rows[2].y = v9; + rs.rows[2].z = v10; + rs.rows[2].w = v11; } else { - rs.rows[0].x = v0; rs.rows[0].y = v1; rs.rows[0].z = v2; - rs.rows[1].x = v3; rs.rows[1].y = v4; rs.rows[1].z = v5; - rs.rows[2].x = v6; rs.rows[2].y = v7; rs.rows[2].z = v8; - rs.rows[3].x = v9; rs.rows[3].y = v10; rs.rows[3].z = v11; + rs.rows[0].x = v0; + rs.rows[0].y = v1; + rs.rows[0].z = v2; + rs.rows[1].x = v3; + rs.rows[1].y = v4; + rs.rows[1].z = v5; + rs.rows[2].x = v6; + rs.rows[2].y = v7; + rs.rows[2].z = v8; + rs.rows[3].x = v9; + rs.rows[3].y = v10; + rs.rows[3].z = v11; } return rs; } template -SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix(T v0, T v1, T v2, T v3, T v4, T v5, T v6, T v7, T v8, T v9, T v10, T v11, T v12, T v13, T v14, T v15) +SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix makeMatrix( + T v0, + T v1, + T v2, + T v3, + T v4, + T v5, + T v6, + T v7, + T v8, + T v9, + T v10, + T v11, + T v12, + T v13, + T v14, + T v15) { Matrix rs; - rs.rows[0].x = v0; rs.rows[0].y = v1; rs.rows[0].z = v2; rs.rows[0].w = v3; - rs.rows[1].x = v4; rs.rows[1].y = v5; rs.rows[1].z = v6; rs.rows[1].w = v7; - rs.rows[2].x = v8; rs.rows[2].y = v9; rs.rows[2].z = v10; rs.rows[2].w = v11; - rs.rows[3].x = v12; rs.rows[3].y = v13; rs.rows[3].z = v14; rs.rows[3].w = v15; + rs.rows[0].x = v0; + rs.rows[0].y = v1; + rs.rows[0].z = v2; + rs.rows[0].w = v3; + rs.rows[1].x = v4; + rs.rows[1].y = v5; + rs.rows[1].z = v6; + rs.rows[1].w = v7; + rs.rows[2].x = v8; + rs.rows[2].y = v9; + rs.rows[2].z = v10; + rs.rows[2].w = v11; + rs.rows[3].x = v12; + rs.rows[3].y = v13; + rs.rows[3].z = v14; + rs.rows[3].w = v15; return rs; } -#define SLANG_MATRIX_BINARY_OP(T, op) \ - template \ - SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix operator op(const Matrix& thisVal, const Matrix& other) \ - { \ - Matrix result;\ - for (int i = 0; i < R; i++) \ - for (int j = 0; j < C; j++) \ - *_slang_vector_get_element_ptr(result.rows+i,j) = _slang_vector_get_element(thisVal.rows[i], j) op _slang_vector_get_element(other.rows[i], j); \ - return result;\ +#define SLANG_MATRIX_BINARY_OP(T, op) \ + template \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix operator op( \ + const Matrix& thisVal, \ + const Matrix& other) \ + { \ + Matrix result; \ + for (int i = 0; i < R; i++) \ + for (int j = 0; j < C; j++) \ + *_slang_vector_get_element_ptr(result.rows + i, j) = \ + _slang_vector_get_element(thisVal.rows[i], j) \ + op _slang_vector_get_element(other.rows[i], j); \ + return result; \ } -#define SLANG_MATRIX_UNARY_OP(T, op) \ - template \ +#define SLANG_MATRIX_UNARY_OP(T, op) \ + template \ SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix operator op(const Matrix& thisVal) \ - { \ - Matrix result;\ - for (int i = 0; i < R; i++) \ - for (int j = 0; j < C; j++) \ - *_slang_vector_get_element_ptr(result.rows+i,j) = op _slang_vector_get_element(thisVal.rows[i], j); \ - return result;\ - } -#define SLANG_INT_MATRIX_OPS(T) \ - SLANG_MATRIX_BINARY_OP(T, +)\ - SLANG_MATRIX_BINARY_OP(T, -)\ - SLANG_MATRIX_BINARY_OP(T, *)\ - SLANG_MATRIX_BINARY_OP(T, / )\ - SLANG_MATRIX_BINARY_OP(T, &)\ - SLANG_MATRIX_BINARY_OP(T, |)\ - SLANG_MATRIX_BINARY_OP(T, &&)\ - SLANG_MATRIX_BINARY_OP(T, ||)\ - SLANG_MATRIX_BINARY_OP(T, ^)\ - SLANG_MATRIX_BINARY_OP(T, %)\ - SLANG_MATRIX_UNARY_OP(T, !)\ + { \ + Matrix result; \ + for (int i = 0; i < R; i++) \ + for (int j = 0; j < C; j++) \ + *_slang_vector_get_element_ptr(result.rows + i, j) = \ + op _slang_vector_get_element(thisVal.rows[i], j); \ + return result; \ + } +#define SLANG_INT_MATRIX_OPS(T) \ + SLANG_MATRIX_BINARY_OP(T, +) \ + SLANG_MATRIX_BINARY_OP(T, -) \ + SLANG_MATRIX_BINARY_OP(T, *) \ + SLANG_MATRIX_BINARY_OP(T, /) \ + SLANG_MATRIX_BINARY_OP(T, &) \ + SLANG_MATRIX_BINARY_OP(T, |) \ + SLANG_MATRIX_BINARY_OP(T, &&) \ + SLANG_MATRIX_BINARY_OP(T, ||) \ + SLANG_MATRIX_BINARY_OP(T, ^) \ + SLANG_MATRIX_BINARY_OP(T, %) \ + SLANG_MATRIX_UNARY_OP(T, !) \ SLANG_MATRIX_UNARY_OP(T, ~) #define SLANG_FLOAT_MATRIX_OPS(T) \ - SLANG_MATRIX_BINARY_OP(T, +)\ - SLANG_MATRIX_BINARY_OP(T, -)\ - SLANG_MATRIX_BINARY_OP(T, *)\ - SLANG_MATRIX_BINARY_OP(T, /)\ + SLANG_MATRIX_BINARY_OP(T, +) \ + SLANG_MATRIX_BINARY_OP(T, -) \ + SLANG_MATRIX_BINARY_OP(T, *) \ + SLANG_MATRIX_BINARY_OP(T, /) \ SLANG_MATRIX_UNARY_OP(T, -) SLANG_INT_MATRIX_OPS(int) SLANG_INT_MATRIX_OPS(uint) @@ -711,48 +960,57 @@ SLANG_FLOAT_MATRIX_OPS(double) #if SLANG_CUDA_ENABLE_HALF SLANG_FLOAT_MATRIX_OPS(__half) #endif -#define SLANG_MATRIX_INT_NEG_OP(T) \ - template\ +#define SLANG_MATRIX_INT_NEG_OP(T) \ + template \ SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix operator-(Matrix thisVal) \ - { \ - Matrix result;\ - for (int i = 0; i < R; i++) \ - for (int j = 0; j < C; j++) \ - *_slang_vector_get_element_ptr(result.rows+i,j) = 0 - _slang_vector_get_element(thisVal.rows[i], j); \ - return result;\ - } - SLANG_MATRIX_INT_NEG_OP(int) - SLANG_MATRIX_INT_NEG_OP(uint) - SLANG_MATRIX_INT_NEG_OP(short) - SLANG_MATRIX_INT_NEG_OP(ushort) - SLANG_MATRIX_INT_NEG_OP(char) - SLANG_MATRIX_INT_NEG_OP(uchar) - SLANG_MATRIX_INT_NEG_OP(longlong) - SLANG_MATRIX_INT_NEG_OP(ulonglong) - -#define SLANG_FLOAT_MATRIX_MOD(T)\ - template \ - SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix operator%(Matrix left, Matrix right) \ - {\ - Matrix result;\ - for (int i = 0; i < R; i++) \ - for (int j = 0; j < C; j++) \ - *_slang_vector_get_element_ptr(result.rows+i,j) = _slang_fmod(_slang_vector_get_element(left.rows[i], j), _slang_vector_get_element(right.rows[i], j)); \ - return result;\ - } - - SLANG_FLOAT_MATRIX_MOD(float) - SLANG_FLOAT_MATRIX_MOD(double) + { \ + Matrix result; \ + for (int i = 0; i < R; i++) \ + for (int j = 0; j < C; j++) \ + *_slang_vector_get_element_ptr(result.rows + i, j) = \ + 0 - _slang_vector_get_element(thisVal.rows[i], j); \ + return result; \ + } +SLANG_MATRIX_INT_NEG_OP(int) +SLANG_MATRIX_INT_NEG_OP(uint) +SLANG_MATRIX_INT_NEG_OP(short) +SLANG_MATRIX_INT_NEG_OP(ushort) +SLANG_MATRIX_INT_NEG_OP(char) +SLANG_MATRIX_INT_NEG_OP(uchar) +SLANG_MATRIX_INT_NEG_OP(longlong) +SLANG_MATRIX_INT_NEG_OP(ulonglong) + +#define SLANG_FLOAT_MATRIX_MOD(T) \ + template \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix operator%( \ + Matrix left, \ + Matrix right) \ + { \ + Matrix result; \ + for (int i = 0; i < R; i++) \ + for (int j = 0; j < C; j++) \ + *_slang_vector_get_element_ptr(result.rows + i, j) = _slang_fmod( \ + _slang_vector_get_element(left.rows[i], j), \ + _slang_vector_get_element(right.rows[i], j)); \ + return result; \ + } + +SLANG_FLOAT_MATRIX_MOD(float) +SLANG_FLOAT_MATRIX_MOD(double) #if SLANG_CUDA_ENABLE_HALF - template - SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix<__half, R, C> operator%(Matrix<__half, R, C> left, Matrix<__half, R, C> right) - { - Matrix<__half, R, C> result; - for (int i = 0; i < R; i++) - for (int j = 0; j < C; j++) - * _slang_vector_get_element_ptr(result.rows + i, j) = __float2half(_slang_fmod(__half2float(_slang_vector_get_element(left.rows[i], j)), __half2float(_slang_vector_get_element(right.rows[i], j)))); - return result; - } +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL Matrix<__half, R, C> operator%( + Matrix<__half, R, C> left, + Matrix<__half, R, C> right) +{ + Matrix<__half, R, C> result; + for (int i = 0; i < R; i++) + for (int j = 0; j < C; j++) + *_slang_vector_get_element_ptr(result.rows + i, j) = __float2half(_slang_fmod( + __half2float(_slang_vector_get_element(left.rows[i], j)), + __half2float(_slang_vector_get_element(right.rows[i], j)))); + return result; +} #endif #undef SLANG_FLOAT_MATRIX_MOD #undef SLANG_MATRIX_BINARY_OP @@ -762,19 +1020,24 @@ SLANG_FLOAT_MATRIX_OPS(__half) #undef SLANG_MATRIX_INT_NEG_OP #undef SLANG_FLOAT_MATRIX_MOD -#define SLANG_SELECT_IMPL(T, N)\ -SLANG_FORCE_INLINE SLANG_CUDA_CALL Vector _slang_select(bool##N condition, Vector v0, Vector v1) \ -{ \ - Vector result; \ - for (int i = 0; i < N; i++) \ - { \ - *_slang_vector_get_element_ptr(&result, i) = _slang_vector_get_element(condition, i) ? _slang_vector_get_element(v0, i) : _slang_vector_get_element(v1, i); \ - } \ - return result; \ -} -#define SLANG_SELECT_T(T)\ - SLANG_SELECT_IMPL(T, 2)\ - SLANG_SELECT_IMPL(T, 3)\ +#define SLANG_SELECT_IMPL(T, N) \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL Vector _slang_select( \ + bool##N condition, \ + Vector v0, \ + Vector v1) \ + { \ + Vector result; \ + for (int i = 0; i < N; i++) \ + { \ + *_slang_vector_get_element_ptr(&result, i) = _slang_vector_get_element(condition, i) \ + ? _slang_vector_get_element(v0, i) \ + : _slang_vector_get_element(v1, i); \ + } \ + return result; \ + } +#define SLANG_SELECT_T(T) \ + SLANG_SELECT_IMPL(T, 2) \ + SLANG_SELECT_IMPL(T, 3) \ SLANG_SELECT_IMPL(T, 4) SLANG_SELECT_T(int) @@ -794,53 +1057,103 @@ SLANG_FORCE_INLINE SLANG_CUDA_CALL T _slang_select(bool condition, T v0, T v1) // // Half support -// +// #if SLANG_CUDA_ENABLE_HALF SLANG_SELECT_T(__half) // Convenience functions ushort -> half -SLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 __ushort_as_half(const ushort2& i) { return __halves2half2(__ushort_as_half(i.x), __ushort_as_half(i.y)); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 __ushort_as_half(const ushort3& i) { return __half3{__ushort_as_half(i.x), __ushort_as_half(i.y), __ushort_as_half(i.z)}; } -SLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 __ushort_as_half(const ushort4& i) { return __half4{ __ushort_as_half(i.x), __ushort_as_half(i.y), __ushort_as_half(i.z), __ushort_as_half(i.w) }; } +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 __ushort_as_half(const ushort2& i) +{ + return __halves2half2(__ushort_as_half(i.x), __ushort_as_half(i.y)); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half3 __ushort_as_half(const ushort3& i) +{ + return __half3{__ushort_as_half(i.x), __ushort_as_half(i.y), __ushort_as_half(i.z)}; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 __ushort_as_half(const ushort4& i) +{ + return __half4{ + __ushort_as_half(i.x), + __ushort_as_half(i.y), + __ushort_as_half(i.z), + __ushort_as_half(i.w)}; +} // Convenience functions half -> ushort -SLANG_FORCE_INLINE SLANG_CUDA_CALL ushort2 __half_as_ushort(const __half2& i) { return make_ushort2(__half_as_ushort(i.x), __half_as_ushort(i.y)); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL ushort3 __half_as_ushort(const __half3& i) { return make_ushort3(__half_as_ushort(i.x), __half_as_ushort(i.y), __half_as_ushort(i.z)); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL ushort4 __half_as_ushort(const __half4& i) { return make_ushort4(__half_as_ushort(i.x), __half_as_ushort(i.y), __half_as_ushort(i.z), __half_as_ushort(i.w)); } +SLANG_FORCE_INLINE SLANG_CUDA_CALL ushort2 __half_as_ushort(const __half2& i) +{ + return make_ushort2(__half_as_ushort(i.x), __half_as_ushort(i.y)); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL ushort3 __half_as_ushort(const __half3& i) +{ + return make_ushort3(__half_as_ushort(i.x), __half_as_ushort(i.y), __half_as_ushort(i.z)); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL ushort4 __half_as_ushort(const __half4& i) +{ + return make_ushort4( + __half_as_ushort(i.x), + __half_as_ushort(i.y), + __half_as_ushort(i.z), + __half_as_ushort(i.w)); +} -// This is a little bit of a hack. Fortunately CUDA has the definitions of the templated types in +// This is a little bit of a hack. Fortunately CUDA has the definitions of the templated types in // include/surface_indirect_functions.h -// Here we find the template definition requires a specialization of __nv_isurf_trait to allow -// a specialization of the surface write functions. -// This *isn't* a problem on the read functions as they don't have a return type that uses this mechanism +// Here we find the template definition requires a specialization of __nv_isurf_trait to allow +// a specialization of the surface write functions. +// This *isn't* a problem on the read functions as they don't have a return type that uses this +// mechanism -template<> struct __nv_isurf_trait<__half> { typedef void type; }; -template<> struct __nv_isurf_trait<__half2> { typedef void type; }; -template<> struct __nv_isurf_trait<__half4> { typedef void type; }; +template<> +struct __nv_isurf_trait<__half> +{ + typedef void type; +}; +template<> +struct __nv_isurf_trait<__half2> +{ + typedef void type; +}; +template<> +struct __nv_isurf_trait<__half4> +{ + typedef void type; +}; #define SLANG_DROP_PARENS(...) __VA_ARGS__ -#define SLANG_SURFACE_READ(FUNC_NAME, TYPE_ARGS, ARGS) \ -template <> \ -SLANG_FORCE_INLINE SLANG_CUDA_CALL __half FUNC_NAME<__half>(cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \ -{ \ - return __ushort_as_half(FUNC_NAME(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \ -} \ -\ -template <> \ -SLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 FUNC_NAME<__half2>(cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \ -{ \ - return __ushort_as_half(FUNC_NAME(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \ -} \ -\ -template <> \ -SLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 FUNC_NAME<__half4>(cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \ -{ \ - return __ushort_as_half(FUNC_NAME(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \ -} +#define SLANG_SURFACE_READ(FUNC_NAME, TYPE_ARGS, ARGS) \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL __half FUNC_NAME<__half>( \ + cudaSurfaceObject_t surfObj, \ + SLANG_DROP_PARENS TYPE_ARGS, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + return __ushort_as_half(FUNC_NAME(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \ + } \ + \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL __half2 FUNC_NAME<__half2>( \ + cudaSurfaceObject_t surfObj, \ + SLANG_DROP_PARENS TYPE_ARGS, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + return __ushort_as_half( \ + FUNC_NAME(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \ + } \ + \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL __half4 FUNC_NAME<__half4>( \ + cudaSurfaceObject_t surfObj, \ + SLANG_DROP_PARENS TYPE_ARGS, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + return __ushort_as_half( \ + FUNC_NAME(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \ + } SLANG_SURFACE_READ(surf1Dread, (int x), (x)) SLANG_SURFACE_READ(surf2Dread, (int x, int y), (x, y)) @@ -850,24 +1163,36 @@ SLANG_SURFACE_READ(surf2DLayeredread, (int x, int y, int layer), (x, y, layer)) SLANG_SURFACE_READ(surfCubemapread, (int x, int y, int face), (x, y, face)) SLANG_SURFACE_READ(surfCubemapLayeredread, (int x, int y, int layerFace), (x, y, layerFace)) -#define SLANG_SURFACE_WRITE(FUNC_NAME, TYPE_ARGS, ARGS) \ -template <> \ -SLANG_FORCE_INLINE SLANG_CUDA_CALL void FUNC_NAME<__half>(__half data, cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \ -{ \ - FUNC_NAME(__half_as_ushort(data), surfObj, SLANG_DROP_PARENS ARGS, boundaryMode); \ -} \ -\ -template <> \ -SLANG_FORCE_INLINE SLANG_CUDA_CALL void FUNC_NAME<__half2>(__half2 data, cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \ -{ \ - FUNC_NAME(__half_as_ushort(data), surfObj, SLANG_DROP_PARENS ARGS, boundaryMode); \ -} \ -\ -template <> \ -SLANG_FORCE_INLINE SLANG_CUDA_CALL void FUNC_NAME<__half4>(__half4 data, cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \ -{ \ - FUNC_NAME(__half_as_ushort(data), surfObj, SLANG_DROP_PARENS ARGS, boundaryMode); \ -} +#define SLANG_SURFACE_WRITE(FUNC_NAME, TYPE_ARGS, ARGS) \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL void FUNC_NAME<__half>( \ + __half data, \ + cudaSurfaceObject_t surfObj, \ + SLANG_DROP_PARENS TYPE_ARGS, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + FUNC_NAME(__half_as_ushort(data), surfObj, SLANG_DROP_PARENS ARGS, boundaryMode); \ + } \ + \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL void FUNC_NAME<__half2>( \ + __half2 data, \ + cudaSurfaceObject_t surfObj, \ + SLANG_DROP_PARENS TYPE_ARGS, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + FUNC_NAME(__half_as_ushort(data), surfObj, SLANG_DROP_PARENS ARGS, boundaryMode); \ + } \ + \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL void FUNC_NAME<__half4>( \ + __half4 data, \ + cudaSurfaceObject_t surfObj, \ + SLANG_DROP_PARENS TYPE_ARGS, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + FUNC_NAME(__half_as_ushort(data), surfObj, SLANG_DROP_PARENS ARGS, boundaryMode); \ + } SLANG_SURFACE_WRITE(surf1Dwrite, (int x), (x)) SLANG_SURFACE_WRITE(surf2Dwrite, (int x, int y), (x, y)) @@ -878,38 +1203,54 @@ SLANG_SURFACE_WRITE(surfCubemapwrite, (int x, int y, int face), (x, y, face)) SLANG_SURFACE_WRITE(surfCubemapLayeredwrite, (int x, int y, int layerFace), (x, y, layerFace)) // ! Hack to test out reading !!! -// Only works converting *from* half - -//template -//SLANG_FORCE_INLINE SLANG_CUDA_CALL T surf2Dread_convert(cudaSurfaceObject_t surfObj, int x, int y, cudaSurfaceBoundaryMode boundaryMode); - -#define SLANG_SURFACE_READ_HALF_CONVERT(FUNC_NAME, TYPE_ARGS, ARGS) \ -\ -template \ -SLANG_FORCE_INLINE SLANG_CUDA_CALL T FUNC_NAME##_convert(cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode); \ -\ -template <> \ -SLANG_FORCE_INLINE SLANG_CUDA_CALL float FUNC_NAME##_convert(cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \ -{ \ - return __ushort_as_half(FUNC_NAME(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \ -} \ -\ -template <> \ -SLANG_FORCE_INLINE SLANG_CUDA_CALL float2 FUNC_NAME##_convert(cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \ -{ \ - const __half2 v = __ushort_as_half(FUNC_NAME(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \ - return float2{v.x, v.y}; \ -} \ -\ -template <> \ -SLANG_FORCE_INLINE SLANG_CUDA_CALL float4 FUNC_NAME##_convert(cudaSurfaceObject_t surfObj, SLANG_DROP_PARENS TYPE_ARGS, cudaSurfaceBoundaryMode boundaryMode) \ -{ \ - const __half4 v = __ushort_as_half(FUNC_NAME(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \ - return float4{v.x, v.y, v.z, v.w}; \ -} - -SLANG_SURFACE_READ_HALF_CONVERT(surf1Dread, (int x), (x)) -SLANG_SURFACE_READ_HALF_CONVERT(surf2Dread, (int x, int y), (x, y)) +// Only works converting *from* half + +// template +// SLANG_FORCE_INLINE SLANG_CUDA_CALL T surf2Dread_convert(cudaSurfaceObject_t surfObj, int x, int +// y, cudaSurfaceBoundaryMode boundaryMode); + +#define SLANG_SURFACE_READ_HALF_CONVERT(FUNC_NAME, TYPE_ARGS, ARGS) \ + \ + template \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL T FUNC_NAME##_convert( \ + cudaSurfaceObject_t surfObj, \ + SLANG_DROP_PARENS TYPE_ARGS, \ + cudaSurfaceBoundaryMode boundaryMode); \ + \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL float FUNC_NAME##_convert( \ + cudaSurfaceObject_t surfObj, \ + SLANG_DROP_PARENS TYPE_ARGS, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + return __ushort_as_half( \ + FUNC_NAME(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \ + } \ + \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL float2 FUNC_NAME##_convert( \ + cudaSurfaceObject_t surfObj, \ + SLANG_DROP_PARENS TYPE_ARGS, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + const __half2 v = \ + __ushort_as_half(FUNC_NAME(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \ + return float2{v.x, v.y}; \ + } \ + \ + template<> \ + SLANG_FORCE_INLINE SLANG_CUDA_CALL float4 FUNC_NAME##_convert( \ + cudaSurfaceObject_t surfObj, \ + SLANG_DROP_PARENS TYPE_ARGS, \ + cudaSurfaceBoundaryMode boundaryMode) \ + { \ + const __half4 v = \ + __ushort_as_half(FUNC_NAME(surfObj, SLANG_DROP_PARENS ARGS, boundaryMode)); \ + return float4{v.x, v.y, v.z, v.w}; \ + } + +SLANG_SURFACE_READ_HALF_CONVERT(surf1Dread, (int x), (x)) +SLANG_SURFACE_READ_HALF_CONVERT(surf2Dread, (int x, int y), (x, y)) SLANG_SURFACE_READ_HALF_CONVERT(surf3Dread, (int x, int y, int z), (x, y, z)) #endif @@ -917,178 +1258,506 @@ SLANG_SURFACE_READ_HALF_CONVERT(surf3Dread, (int x, int y, int z), (x, y, z)) // Support for doing format conversion when writing to a surface/RWTexture // NOTE! For normal surface access x values are *byte* addressed. -// For the _convert versions they are *not*. They don't need to be because sust.p does not require it. +// For the _convert versions they are *not*. They don't need to be because sust.p does not require +// it. -template -SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert(T, cudaSurfaceObject_t surfObj, int x, cudaSurfaceBoundaryMode boundaryMode); -template -SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert(T, cudaSurfaceObject_t surfObj, int x, int y, cudaSurfaceBoundaryMode boundaryMode); -template -SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert(T, cudaSurfaceObject_t surfObj, int x, int y, int z, cudaSurfaceBoundaryMode boundaryMode); +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert( + T, + cudaSurfaceObject_t surfObj, + int x, + cudaSurfaceBoundaryMode boundaryMode); +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert( + T, + cudaSurfaceObject_t surfObj, + int x, + int y, + cudaSurfaceBoundaryMode boundaryMode); +template +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert( + T, + cudaSurfaceObject_t surfObj, + int x, + int y, + int z, + cudaSurfaceBoundaryMode boundaryMode); // https://docs.nvidia.com/cuda/inline-ptx-assembly/index.html // https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#surface-instructions-sust // Float -template <> -SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert(float v, cudaSurfaceObject_t surfObj, int x, cudaSurfaceBoundaryMode boundaryMode) +template<> +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert( + float v, + cudaSurfaceObject_t surfObj, + int x, + cudaSurfaceBoundaryMode boundaryMode) { - asm volatile ( "{sust.p.1d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1}], {%2};}\n\t" :: "l"(surfObj),"r"(x),"f"(v)); + asm volatile( + "{sust.p.1d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1}], {%2};}\n\t" ::"l"(surfObj), + "r"(x), + "f"(v)); } - -template <> -SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert(float v, cudaSurfaceObject_t surfObj, int x, int y, cudaSurfaceBoundaryMode boundaryMode) + +template<> +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert( + float v, + cudaSurfaceObject_t surfObj, + int x, + int y, + cudaSurfaceBoundaryMode boundaryMode) { - asm volatile ( "{sust.p.2d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1,%2}], {%3};}\n\t" :: "l"(surfObj),"r"(x),"r"(y),"f"(v)); + asm volatile( + "{sust.p.2d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1,%2}], {%3};}\n\t" ::"l"(surfObj), + "r"(x), + "r"(y), + "f"(v)); } -template <> -SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert(float v, cudaSurfaceObject_t surfObj, int x, int y, int z, cudaSurfaceBoundaryMode boundaryMode) -{ - asm volatile ( "{sust.p.2d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1,%2,%3}], {%4};}\n\t" :: "l"(surfObj),"r"(x),"r"(y),"r"(z),"f"(v)); +template<> +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert( + float v, + cudaSurfaceObject_t surfObj, + int x, + int y, + int z, + cudaSurfaceBoundaryMode boundaryMode) +{ + asm volatile( + "{sust.p.2d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1,%2,%3}], {%4};}\n\t" ::"l"(surfObj), + "r"(x), + "r"(y), + "r"(z), + "f"(v)); } // Float2 -template <> -SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert(float2 v, cudaSurfaceObject_t surfObj, int x, cudaSurfaceBoundaryMode boundaryMode) +template<> +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert( + float2 v, + cudaSurfaceObject_t surfObj, + int x, + cudaSurfaceBoundaryMode boundaryMode) { const float vx = v.x, vy = v.y; - asm volatile ( "{sust.p.1d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1}], {%2,%3};}\n\t" :: "l"(surfObj),"r"(x),"f"(vx),"f"(vy)); + asm volatile( + "{sust.p.1d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1}], {%2,%3};}\n\t" ::"l"(surfObj), + "r"(x), + "f"(vx), + "f"(vy)); } - -template <> -SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert(float2 v, cudaSurfaceObject_t surfObj, int x, int y, cudaSurfaceBoundaryMode boundaryMode) + +template<> +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert( + float2 v, + cudaSurfaceObject_t surfObj, + int x, + int y, + cudaSurfaceBoundaryMode boundaryMode) { const float vx = v.x, vy = v.y; - asm volatile ( "{sust.p.2d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1,%2}], {%3,%4};}\n\t" :: "l"(surfObj),"r"(x),"r"(y),"f"(vx),"f"(vy)); + asm volatile( + "{sust.p.2d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1,%2}], {%3,%4};}\n\t" ::"l"(surfObj), + "r"(x), + "r"(y), + "f"(vx), + "f"(vy)); } -template <> -SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert(float2 v, cudaSurfaceObject_t surfObj, int x, int y, int z, cudaSurfaceBoundaryMode boundaryMode) +template<> +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert( + float2 v, + cudaSurfaceObject_t surfObj, + int x, + int y, + int z, + cudaSurfaceBoundaryMode boundaryMode) { const float vx = v.x, vy = v.y; - asm volatile ( "{sust.p.2d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1,%2,%3}], {%4,%5};}\n\t" :: "l"(surfObj),"r"(x),"r"(y),"r"(z),"f"(vx),"f"(vy)); + asm volatile( + "{sust.p.2d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1,%2,%3}], {%4,%5};}\n\t" ::"l"(surfObj), + "r"(x), + "r"(y), + "r"(z), + "f"(vx), + "f"(vy)); } // Float4 -template <> -SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert(float4 v, cudaSurfaceObject_t surfObj, int x, cudaSurfaceBoundaryMode boundaryMode) +template<> +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf1Dwrite_convert( + float4 v, + cudaSurfaceObject_t surfObj, + int x, + cudaSurfaceBoundaryMode boundaryMode) { const float vx = v.x, vy = v.y, vz = v.z, vw = v.w; - asm volatile ( "{sust.p.1d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1}], {%2,%3,%4,%5};}\n\t" :: "l"(surfObj),"r"(x),"f"(vx),"f"(vy),"f"(vz),"f"(vw)); + asm volatile( + "{sust.p.1d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1}], {%2,%3,%4,%5};}\n\t" ::"l"(surfObj), + "r"(x), + "f"(vx), + "f"(vy), + "f"(vz), + "f"(vw)); } - -template <> -SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert(float4 v, cudaSurfaceObject_t surfObj, int x, int y, cudaSurfaceBoundaryMode boundaryMode) + +template<> +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf2Dwrite_convert( + float4 v, + cudaSurfaceObject_t surfObj, + int x, + int y, + cudaSurfaceBoundaryMode boundaryMode) { const float vx = v.x, vy = v.y, vz = v.z, vw = v.w; - asm volatile ( "{sust.p.2d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1,%2}], {%3,%4,%5,%6};}\n\t" :: "l"(surfObj),"r"(x),"r"(y),"f"(vx),"f"(vy),"f"(vz),"f"(vw)); + asm volatile( + "{sust.p.2d.b32." SLANG_PTX_BOUNDARY_MODE + " [%0, {%1,%2}], {%3,%4,%5,%6};}\n\t" ::"l"(surfObj), + "r"(x), + "r"(y), + "f"(vx), + "f"(vy), + "f"(vz), + "f"(vw)); } -template <> -SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert(float4 v, cudaSurfaceObject_t surfObj, int x, int y, int z, cudaSurfaceBoundaryMode boundaryMode) +template<> +SLANG_FORCE_INLINE SLANG_CUDA_CALL void surf3Dwrite_convert( + float4 v, + cudaSurfaceObject_t surfObj, + int x, + int y, + int z, + cudaSurfaceBoundaryMode boundaryMode) { const float vx = v.x, vy = v.y, vz = v.z, vw = v.w; - asm volatile ( "{sust.p.2d.b32." SLANG_PTX_BOUNDARY_MODE " [%0, {%1,%2,%3}], {%4,%5,%6,%7};}\n\t" :: "l"(surfObj),"r"(x),"r"(y),"r"(z),"f"(vx),"f"(vy),"f"(vz),"f"(vw)); + asm volatile( + "{sust.p.2d.b32." SLANG_PTX_BOUNDARY_MODE + " [%0, {%1,%2,%3}], {%4,%5,%6,%7};}\n\t" ::"l"(surfObj), + "r"(x), + "r"(y), + "r"(z), + "f"(vx), + "f"(vy), + "f"(vz), + "f"(vw)); } // ----------------------------- F32 ----------------------------------------- -// Unary -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_ceil(float f) { return ::ceilf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_floor(float f) { return ::floorf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_round(float f) { return ::roundf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_sin(float f) { return ::sinf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_cos(float f) { return ::cosf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL void F32_sincos(float f, float* s, float* c) { ::sincosf(f, s, c); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_tan(float f) { return ::tanf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_asin(float f) { return ::asinf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_acos(float f) { return ::acosf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_atan(float f) { return ::atanf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_sinh(float f) { return ::sinhf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_cosh(float f) { return ::coshf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_tanh(float f) { return ::tanhf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_log2(float f) { return ::log2f(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_log(float f) { return ::logf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_log10(float f) { return ::log10f(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_exp2(float f) { return ::exp2f(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_exp(float f) { return ::expf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_abs(float f) { return ::fabsf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_trunc(float f) { return ::truncf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_sqrt(float f) { return ::sqrtf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_rsqrt(float f) { return ::rsqrtf(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_sign(float f) { return ( f == 0.0f) ? f : (( f < 0.0f) ? -1.0f : 1.0f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_frac(float f) { return f - F32_floor(f); } - -SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F32_isnan(float f) { return isnan(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F32_isfinite(float f) { return isfinite(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F32_isinf(float f) { return isinf(f); } +// Unary +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_ceil(float f) +{ + return ::ceilf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_floor(float f) +{ + return ::floorf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_round(float f) +{ + return ::roundf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_sin(float f) +{ + return ::sinf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_cos(float f) +{ + return ::cosf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL void F32_sincos(float f, float* s, float* c) +{ + ::sincosf(f, s, c); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_tan(float f) +{ + return ::tanf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_asin(float f) +{ + return ::asinf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_acos(float f) +{ + return ::acosf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_atan(float f) +{ + return ::atanf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_sinh(float f) +{ + return ::sinhf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_cosh(float f) +{ + return ::coshf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_tanh(float f) +{ + return ::tanhf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_log2(float f) +{ + return ::log2f(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_log(float f) +{ + return ::logf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_log10(float f) +{ + return ::log10f(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_exp2(float f) +{ + return ::exp2f(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_exp(float f) +{ + return ::expf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_abs(float f) +{ + return ::fabsf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_trunc(float f) +{ + return ::truncf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_sqrt(float f) +{ + return ::sqrtf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_rsqrt(float f) +{ + return ::rsqrtf(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_sign(float f) +{ + return (f == 0.0f) ? f : ((f < 0.0f) ? -1.0f : 1.0f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_frac(float f) +{ + return f - F32_floor(f); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F32_isnan(float f) +{ + return isnan(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F32_isfinite(float f) +{ + return isfinite(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F32_isinf(float f) +{ + return isinf(f); +} // Binary -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_min(float a, float b) { return ::fminf(a, b); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_max(float a, float b) { return ::fmaxf(a, b); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_pow(float a, float b) { return ::powf(a, b); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_fmod(float a, float b) { return ::fmodf(a, b); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_remainder(float a, float b) { return ::remainderf(a, b); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_atan2(float a, float b) { return float(::atan2(a, b)); } +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_min(float a, float b) +{ + return ::fminf(a, b); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_max(float a, float b) +{ + return ::fmaxf(a, b); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_pow(float a, float b) +{ + return ::powf(a, b); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_fmod(float a, float b) +{ + return ::fmodf(a, b); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_remainder(float a, float b) +{ + return ::remainderf(a, b); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_atan2(float a, float b) +{ + return float(::atan2(a, b)); +} -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_frexp(float x, int* e) { return frexpf(x, e); } +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_frexp(float x, int* e) +{ + return frexpf(x, e); +} SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_modf(float x, float* ip) { return ::modff(x, ip); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t F32_asuint(float f) { Union32 u; u.f = f; return u.u; } -SLANG_FORCE_INLINE SLANG_CUDA_CALL int32_t F32_asint(float f) { Union32 u; u.f = f; return u.i; } +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t F32_asuint(float f) +{ + Union32 u; + u.f = f; + return u.u; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL int32_t F32_asint(float f) +{ + Union32 u; + u.f = f; + return u.i; +} // Ternary -SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_fma(float a, float b, float c) { return ::fmaf(a, b, c); } +SLANG_FORCE_INLINE SLANG_CUDA_CALL float F32_fma(float a, float b, float c) +{ + return ::fmaf(a, b, c); +} // ----------------------------- F64 ----------------------------------------- -// Unary -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_ceil(double f) { return ::ceil(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_floor(double f) { return ::floor(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_round(double f) { return ::round(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_sin(double f) { return ::sin(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_cos(double f) { return ::cos(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL void F64_sincos(double f, double* s, double* c) { ::sincos(f, s, c); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_tan(double f) { return ::tan(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_asin(double f) { return ::asin(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_acos(double f) { return ::acos(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_atan(double f) { return ::atan(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_sinh(double f) { return ::sinh(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_cosh(double f) { return ::cosh(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_tanh(double f) { return ::tanh(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_log2(double f) { return ::log2(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_log(double f) { return ::log(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_log10(float f) { return ::log10(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_exp2(double f) { return ::exp2(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_exp(double f) { return ::exp(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_abs(double f) { return ::fabs(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_trunc(double f) { return ::trunc(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_sqrt(double f) { return ::sqrt(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_rsqrt(double f) { return ::rsqrt(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_sign(double f) { return (f == 0.0) ? f : ((f < 0.0) ? -1.0 : 1.0); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_frac(double f) { return f - F64_floor(f); } - -SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F64_isnan(double f) { return isnan(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F64_isfinite(double f) { return isfinite(f); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F64_isinf(double f) { return isinf(f); } +// Unary +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_ceil(double f) +{ + return ::ceil(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_floor(double f) +{ + return ::floor(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_round(double f) +{ + return ::round(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_sin(double f) +{ + return ::sin(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_cos(double f) +{ + return ::cos(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL void F64_sincos(double f, double* s, double* c) +{ + ::sincos(f, s, c); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_tan(double f) +{ + return ::tan(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_asin(double f) +{ + return ::asin(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_acos(double f) +{ + return ::acos(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_atan(double f) +{ + return ::atan(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_sinh(double f) +{ + return ::sinh(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_cosh(double f) +{ + return ::cosh(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_tanh(double f) +{ + return ::tanh(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_log2(double f) +{ + return ::log2(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_log(double f) +{ + return ::log(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_log10(float f) +{ + return ::log10(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_exp2(double f) +{ + return ::exp2(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_exp(double f) +{ + return ::exp(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_abs(double f) +{ + return ::fabs(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_trunc(double f) +{ + return ::trunc(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_sqrt(double f) +{ + return ::sqrt(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_rsqrt(double f) +{ + return ::rsqrt(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_sign(double f) +{ + return (f == 0.0) ? f : ((f < 0.0) ? -1.0 : 1.0); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_frac(double f) +{ + return f - F64_floor(f); +} + +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F64_isnan(double f) +{ + return isnan(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F64_isfinite(double f) +{ + return isfinite(f); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL bool F64_isinf(double f) +{ + return isinf(f); +} // Binary -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_min(double a, double b) { return ::fmin(a, b); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_max(double a, double b) { return ::fmax(a, b); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_pow(double a, double b) { return ::pow(a, b); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_fmod(double a, double b) { return ::fmod(a, b); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_remainder(double a, double b) { return ::remainder(a, b); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_atan2(double a, double b) { return ::atan2(a, b); } +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_min(double a, double b) +{ + return ::fmin(a, b); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_max(double a, double b) +{ + return ::fmax(a, b); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_pow(double a, double b) +{ + return ::pow(a, b); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_fmod(double a, double b) +{ + return ::fmod(a, b); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_remainder(double a, double b) +{ + return ::remainder(a, b); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_atan2(double a, double b) +{ + return ::atan2(a, b); +} -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_frexp(double x, int* e) { return ::frexp(x, e); } +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_frexp(double x, int* e) +{ + return ::frexp(x, e); +} SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_modf(double x, double* ip) { @@ -1112,20 +1781,40 @@ SLANG_FORCE_INLINE SLANG_CUDA_CALL void F64_asint(double d, int32_t* low, int32_ } // Ternary -SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_fma(double a, double b, double c) { return ::fma(a, b, c); } +SLANG_FORCE_INLINE SLANG_CUDA_CALL double F64_fma(double a, double b, double c) +{ + return ::fma(a, b, c); +} // ----------------------------- I32 ----------------------------------------- // Unary -SLANG_FORCE_INLINE SLANG_CUDA_CALL int32_t I32_abs(int32_t f) { return (f < 0) ? -f : f; } +SLANG_FORCE_INLINE SLANG_CUDA_CALL int32_t I32_abs(int32_t f) +{ + return (f < 0) ? -f : f; +} // Binary -SLANG_FORCE_INLINE SLANG_CUDA_CALL int32_t I32_min(int32_t a, int32_t b) { return a < b ? a : b; } -SLANG_FORCE_INLINE SLANG_CUDA_CALL int32_t I32_max(int32_t a, int32_t b) { return a > b ? a : b; } +SLANG_FORCE_INLINE SLANG_CUDA_CALL int32_t I32_min(int32_t a, int32_t b) +{ + return a < b ? a : b; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL int32_t I32_max(int32_t a, int32_t b) +{ + return a > b ? a : b; +} -SLANG_FORCE_INLINE SLANG_CUDA_CALL float I32_asfloat(int32_t x) { Union32 u; u.i = x; return u.f; } -SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t I32_asuint(int32_t x) { return uint32_t(x); } -SLANG_FORCE_INLINE SLANG_CUDA_CALL double I32_asdouble(int32_t low, int32_t hi ) +SLANG_FORCE_INLINE SLANG_CUDA_CALL float I32_asfloat(int32_t x) +{ + Union32 u; + u.i = x; + return u.f; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t I32_asuint(int32_t x) +{ + return uint32_t(x); +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL double I32_asdouble(int32_t low, int32_t hi) { Union64 u; u.u = (uint64_t(hi) << 32) | uint32_t(low); @@ -1134,15 +1823,32 @@ SLANG_FORCE_INLINE SLANG_CUDA_CALL double I32_asdouble(int32_t low, int32_t hi ) // ----------------------------- U32 ----------------------------------------- -// Unary -SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U32_abs(uint32_t f) { return f; } +// Unary +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U32_abs(uint32_t f) +{ + return f; +} // Binary -SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U32_min(uint32_t a, uint32_t b) { return a < b ? a : b; } -SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U32_max(uint32_t a, uint32_t b) { return a > b ? a : b; } +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U32_min(uint32_t a, uint32_t b) +{ + return a < b ? a : b; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U32_max(uint32_t a, uint32_t b) +{ + return a > b ? a : b; +} -SLANG_FORCE_INLINE SLANG_CUDA_CALL float U32_asfloat(uint32_t x) { Union32 u; u.u = x; return u.f; } -SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U32_asint(int32_t x) { return uint32_t(x); } +SLANG_FORCE_INLINE SLANG_CUDA_CALL float U32_asfloat(uint32_t x) +{ + Union32 u; + u.u = x; + return u.f; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U32_asint(int32_t x) +{ + return uint32_t(x); +} SLANG_FORCE_INLINE SLANG_CUDA_CALL double U32_asdouble(uint32_t low, uint32_t hi) { @@ -1160,17 +1866,35 @@ SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U32_countbits(uint32_t v) // ----------------------------- I64 ----------------------------------------- -SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t I64_abs(int64_t f) { return (f < 0) ? -f : f; } +SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t I64_abs(int64_t f) +{ + return (f < 0) ? -f : f; +} -SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t I64_min(int64_t a, int64_t b) { return a < b ? a : b; } -SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t I64_max(int64_t a, int64_t b) { return a > b ? a : b; } +SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t I64_min(int64_t a, int64_t b) +{ + return a < b ? a : b; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t I64_max(int64_t a, int64_t b) +{ + return a > b ? a : b; +} // ----------------------------- U64 ----------------------------------------- -SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t U64_abs(uint64_t f) { return f; } +SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t U64_abs(uint64_t f) +{ + return f; +} -SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t U64_min(uint64_t a, uint64_t b) { return a < b ? a : b; } -SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t U64_max(uint64_t a, uint64_t b) { return a > b ? a : b; } +SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t U64_min(uint64_t a, uint64_t b) +{ + return a < b ? a : b; +} +SLANG_FORCE_INLINE SLANG_CUDA_CALL int64_t U64_max(uint64_t a, uint64_t b) +{ + return a > b ? a : b; +} SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U64_countbits(uint64_t v) { @@ -1185,7 +1909,7 @@ SLANG_FORCE_INLINE SLANG_CUDA_CALL uint32_t U64_countbits(uint64_t v) // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-structuredbuffer-getdimensions // Missing Load(_In_ int Location, _Out_ uint Status); -template +template struct StructuredBuffer { SLANG_CUDA_CALL const T& operator[](size_t index) const @@ -1205,7 +1929,11 @@ struct StructuredBuffer } #ifndef SLANG_CUDA_STRUCTURED_BUFFER_NO_COUNT - SLANG_CUDA_CALL void GetDimensions(uint32_t* outNumStructs, uint32_t* outStride) { *outNumStructs = uint32_t(count); *outStride = uint32_t(sizeof(T)); } + SLANG_CUDA_CALL void GetDimensions(uint32_t* outNumStructs, uint32_t* outStride) + { + *outNumStructs = uint32_t(count); + *outStride = uint32_t(sizeof(T)); + } #endif T* data; @@ -1214,7 +1942,7 @@ struct StructuredBuffer #endif }; -template +template struct RWStructuredBuffer : StructuredBuffer { SLANG_CUDA_CALL T& operator[](size_t index) const @@ -1230,28 +1958,28 @@ struct RWStructuredBuffer : StructuredBuffer struct ByteAddressBuffer { SLANG_CUDA_CALL void GetDimensions(uint32_t* outDim) const { *outDim = uint32_t(sizeInBytes); } - SLANG_CUDA_CALL uint32_t Load(size_t index) const - { + SLANG_CUDA_CALL uint32_t Load(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes); - return data[index >> 2]; + return data[index >> 2]; } - SLANG_CUDA_CALL uint2 Load2(size_t index) const - { - SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes); - const size_t dataIdx = index >> 2; - return uint2{data[dataIdx], data[dataIdx + 1]}; + SLANG_CUDA_CALL uint2 Load2(size_t index) const + { + SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes); + const size_t dataIdx = index >> 2; + return uint2{data[dataIdx], data[dataIdx + 1]}; } - SLANG_CUDA_CALL uint3 Load3(size_t index) const - { + SLANG_CUDA_CALL uint3 Load3(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes); - const size_t dataIdx = index >> 2; - return uint3{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2]}; + const size_t dataIdx = index >> 2; + return uint3{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2]}; } - SLANG_CUDA_CALL uint4 Load4(size_t index) const - { + SLANG_CUDA_CALL uint4 Load4(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes); - const size_t dataIdx = index >> 2; - return uint4{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2], data[dataIdx + 3]}; + const size_t dataIdx = index >> 2; + return uint4{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2], data[dataIdx + 3]}; } template SLANG_CUDA_CALL T Load(size_t index) const @@ -1270,38 +1998,38 @@ struct ByteAddressBuffer return rs; } const uint32_t* data; - size_t sizeInBytes; //< Must be multiple of 4 + size_t sizeInBytes; //< Must be multiple of 4 }; // https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-rwbyteaddressbuffer -// Missing support for Atomic operations +// Missing support for Atomic operations // Missing support for Load with status struct RWByteAddressBuffer { SLANG_CUDA_CALL void GetDimensions(uint32_t* outDim) const { *outDim = uint32_t(sizeInBytes); } - - SLANG_CUDA_CALL uint32_t Load(size_t index) const - { + + SLANG_CUDA_CALL uint32_t Load(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes); - return data[index >> 2]; + return data[index >> 2]; } - SLANG_CUDA_CALL uint2 Load2(size_t index) const - { + SLANG_CUDA_CALL uint2 Load2(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes); - const size_t dataIdx = index >> 2; - return uint2{data[dataIdx], data[dataIdx + 1]}; + const size_t dataIdx = index >> 2; + return uint2{data[dataIdx], data[dataIdx + 1]}; } - SLANG_CUDA_CALL uint3 Load3(size_t index) const - { + SLANG_CUDA_CALL uint3 Load3(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes); - const size_t dataIdx = index >> 2; - return uint3{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2]}; + const size_t dataIdx = index >> 2; + return uint3{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2]}; } - SLANG_CUDA_CALL uint4 Load4(size_t index) const - { + SLANG_CUDA_CALL uint4 Load4(size_t index) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes); - const size_t dataIdx = index >> 2; - return uint4{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2], data[dataIdx + 3]}; + const size_t dataIdx = index >> 2; + return uint4{data[dataIdx], data[dataIdx + 1], data[dataIdx + 2], data[dataIdx + 3]}; } template SLANG_CUDA_CALL T Load(size_t index) const @@ -1311,31 +2039,31 @@ struct RWByteAddressBuffer memcpy(&data, ((const char*)this->data) + index, sizeof(T)); return data; } - - SLANG_CUDA_CALL void Store(size_t index, uint32_t v) const - { + + SLANG_CUDA_CALL void Store(size_t index, uint32_t v) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 4, sizeInBytes); - data[index >> 2] = v; + data[index >> 2] = v; } - SLANG_CUDA_CALL void Store2(size_t index, uint2 v) const - { + SLANG_CUDA_CALL void Store2(size_t index, uint2 v) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 8, sizeInBytes); - const size_t dataIdx = index >> 2; + const size_t dataIdx = index >> 2; data[dataIdx + 0] = v.x; data[dataIdx + 1] = v.y; } - SLANG_CUDA_CALL void Store3(size_t index, uint3 v) const - { + SLANG_CUDA_CALL void Store3(size_t index, uint3 v) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 12, sizeInBytes); - const size_t dataIdx = index >> 2; + const size_t dataIdx = index >> 2; data[dataIdx + 0] = v.x; data[dataIdx + 1] = v.y; data[dataIdx + 2] = v.z; } - SLANG_CUDA_CALL void Store4(size_t index, uint4 v) const - { + SLANG_CUDA_CALL void Store4(size_t index, uint4 v) const + { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, 16, sizeInBytes); - const size_t dataIdx = index >> 2; + const size_t dataIdx = index >> 2; data[dataIdx + 0] = v.x; data[dataIdx + 1] = v.y; data[dataIdx + 2] = v.z; @@ -1347,9 +2075,9 @@ struct RWByteAddressBuffer SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes); memcpy((char*)data + index, &value, sizeof(T)); } - - /// Can be used in the core module to gain access - template + + /// Can be used in the core module to gain access + template SLANG_CUDA_CALL T* _getPtrAt(size_t index) { SLANG_BOUND_CHECK_BYTE_ADDRESS(index, sizeof(T), sizeInBytes); @@ -1364,69 +2092,71 @@ struct RWByteAddressBuffer return rs; } uint32_t* data; - size_t sizeInBytes; //< Must be multiple of 4 + size_t sizeInBytes; //< Must be multiple of 4 }; // ---------------------- Wave -------------------------------------- -// TODO(JS): It appears that cuda does not have a simple way to get a lane index. -// -// Another approach could be... -// laneId = ((threadIdx.z * blockDim.y + threadIdx.y) * blockDim.x + threadIdx.x) & SLANG_CUDA_WARP_MASK -// If that is really true another way to do this, would be for code generator to add this function -// with the [numthreads] baked in. -// -// For now I'll just assume you have a launch that makes the following correct if the kernel uses WaveGetLaneIndex() +// TODO(JS): It appears that cuda does not have a simple way to get a lane index. +// +// Another approach could be... +// laneId = ((threadIdx.z * blockDim.y + threadIdx.y) * blockDim.x + threadIdx.x) & +// SLANG_CUDA_WARP_MASK If that is really true another way to do this, would be for code generator +// to add this function with the [numthreads] baked in. +// +// For now I'll just assume you have a launch that makes the following correct if the kernel uses +// WaveGetLaneIndex() #ifndef SLANG_USE_ASM_LANE_ID - __forceinline__ __device__ uint32_t _getLaneId() +__forceinline__ __device__ uint32_t _getLaneId() { - // If the launch is (or I guess some multiple of the warp size) - // we try this mechanism, which is apparently faster. + // If the launch is (or I guess some multiple of the warp size) + // we try this mechanism, which is apparently faster. return threadIdx.x & SLANG_CUDA_WARP_MASK; } #else __forceinline__ __device__ uint32_t _getLaneId() { // https://stackoverflow.com/questions/44337309/whats-the-most-efficient-way-to-calculate-the-warp-id-lane-id-in-a-1-d-grid# - // This mechanism is not the fastest way to do it, and that is why the other mechanism - // is the default. But the other mechanism relies on a launch that makes the assumption + // This mechanism is not the fastest way to do it, and that is why the other mechanism + // is the default. But the other mechanism relies on a launch that makes the assumption // true. - unsigned ret; - asm volatile ("mov.u32 %0, %laneid;" : "=r"(ret)); + unsigned ret; + asm volatile("mov.u32 %0, %laneid;" : "=r"(ret)); return ret; } #endif typedef int WarpMask; -// It appears that the __activemask() cannot always be used because -// threads need to be converged. -// +// It appears that the __activemask() cannot always be used because +// threads need to be converged. +// // For CUDA the article claims mask has to be used carefully // https://devblogs.nvidia.com/using-cuda-warp-level-primitives/ -// With the Warp intrinsics there is no mask, and it's just the 'active lanes'. +// With the Warp intrinsics there is no mask, and it's just the 'active lanes'. // __activemask() though does not require there is convergence, so that doesn't work. -// -// '__ballot_sync' produces a convergance. -// +// +// '__ballot_sync' produces a convergance. +// // From the CUDA docs: -// ```For __all_sync, __any_sync, and __ballot_sync, a mask must be passed that specifies the threads -// participating in the call. A bit, representing the thread's lane ID, must be set for each participating thread -// to ensure they are properly converged before the intrinsic is executed by the hardware. All active threads named -// in mask must execute the same intrinsic with the same mask, or the result is undefined.``` +// ```For __all_sync, __any_sync, and __ballot_sync, a mask must be passed that specifies the +// threads participating in the call. A bit, representing the thread's lane ID, must be set for each +// participating thread to ensure they are properly converged before the intrinsic is executed by +// the hardware. All active threads named in mask must execute the same intrinsic with the same +// mask, or the result is undefined.``` // // Currently there isn't a mechanism to correctly get the mask without it being passed through. -// Doing so will most likely require some changes to slang code generation to track masks, for now then we use -// _getActiveMask. +// Doing so will most likely require some changes to slang code generation to track masks, for now +// then we use _getActiveMask. // Return mask of all the lanes less than the current lane __forceinline__ __device__ WarpMask _getLaneLtMask() { return (int(1) << _getLaneId()) - 1; -} +} -// TODO(JS): +// TODO(JS): // THIS IS NOT CORRECT! That determining the appropriate active mask requires appropriate // mask tracking. __forceinline__ __device__ WarpMask _getActiveMask() @@ -1478,30 +2208,30 @@ __inline__ __device__ int _waveCalcPow2Offset(WarpMask mask) __inline__ __device__ bool _waveIsFirstLane() { const WarpMask mask = __activemask(); - // We special case bit 0, as that most warps are expected to be fully active. - + // We special case bit 0, as that most warps are expected to be fully active. + // mask & -mask, isolates the lowest set bit. - //return (mask & 1 ) || ((mask & -mask) == (1 << _getLaneId())); - - // This mechanism is most similar to what was in an nVidia post, so assume it is prefered. - return (mask & 1 ) || ((__ffs(mask) - 1) == _getLaneId()); + // return (mask & 1 ) || ((mask & -mask) == (1 << _getLaneId())); + + // This mechanism is most similar to what was in an nVidia post, so assume it is prefered. + return (mask & 1) || ((__ffs(mask) - 1) == _getLaneId()); } -template +template struct WaveOpOr { __inline__ __device__ static T getInitial(T a) { return 0; } __inline__ __device__ static T doOp(T a, T b) { return a | b; } }; -template +template struct WaveOpAnd { __inline__ __device__ static T getInitial(T a) { return ~T(0); } __inline__ __device__ static T doOp(T a, T b) { return a & b; } }; -template +template struct WaveOpXor { __inline__ __device__ static T getInitial(T a) { return 0; } @@ -1509,7 +2239,7 @@ struct WaveOpXor __inline__ __device__ static T doInverse(T a, T b) { return a ^ b; } }; -template +template struct WaveOpAdd { __inline__ __device__ static T getInitial(T a) { return 0; } @@ -1517,77 +2247,166 @@ struct WaveOpAdd __inline__ __device__ static T doInverse(T a, T b) { return a - b; } }; -template +template struct WaveOpMul { __inline__ __device__ static T getInitial(T a) { return T(1); } __inline__ __device__ static T doOp(T a, T b) { return a * b; } - // Using this inverse for int is probably undesirable - because in general it requires T to have more precision - // There is also a performance aspect to it, where divides are generally significantly slower + // Using this inverse for int is probably undesirable - because in general it requires T to have + // more precision There is also a performance aspect to it, where divides are generally + // significantly slower __inline__ __device__ static T doInverse(T a, T b) { return a / b; } }; -template +template struct WaveOpMax { __inline__ __device__ static T getInitial(T a) { return a; } __inline__ __device__ static T doOp(T a, T b) { return a > b ? a : b; } }; -template +template struct WaveOpMin { - __inline__ __device__ static T getInitial(T a) { return a; } + __inline__ __device__ static T getInitial(T a) { return a; } __inline__ __device__ static T doOp(T a, T b) { return a < b ? a : b; } }; -template +template struct ElementTypeTrait; // Scalar -template <> struct ElementTypeTrait { typedef int Type; }; -template <> struct ElementTypeTrait { typedef uint Type; }; -template <> struct ElementTypeTrait { typedef float Type; }; -template <> struct ElementTypeTrait { typedef double Type; }; -template <> struct ElementTypeTrait { typedef uint64_t Type; }; -template <> struct ElementTypeTrait { typedef int64_t Type; }; +template<> +struct ElementTypeTrait +{ + typedef int Type; +}; +template<> +struct ElementTypeTrait +{ + typedef uint Type; +}; +template<> +struct ElementTypeTrait +{ + typedef float Type; +}; +template<> +struct ElementTypeTrait +{ + typedef double Type; +}; +template<> +struct ElementTypeTrait +{ + typedef uint64_t Type; +}; +template<> +struct ElementTypeTrait +{ + typedef int64_t Type; +}; // Vector -template <> struct ElementTypeTrait { typedef int Type; }; -template <> struct ElementTypeTrait { typedef int Type; }; -template <> struct ElementTypeTrait { typedef int Type; }; -template <> struct ElementTypeTrait { typedef int Type; }; - -template <> struct ElementTypeTrait { typedef uint Type; }; -template <> struct ElementTypeTrait { typedef uint Type; }; -template <> struct ElementTypeTrait { typedef uint Type; }; -template <> struct ElementTypeTrait { typedef uint Type; }; - -template <> struct ElementTypeTrait { typedef float Type; }; -template <> struct ElementTypeTrait { typedef float Type; }; -template <> struct ElementTypeTrait { typedef float Type; }; -template <> struct ElementTypeTrait { typedef float Type; }; - -template <> struct ElementTypeTrait { typedef double Type; }; -template <> struct ElementTypeTrait { typedef double Type; }; -template <> struct ElementTypeTrait { typedef double Type; }; -template <> struct ElementTypeTrait { typedef double Type; }; +template<> +struct ElementTypeTrait +{ + typedef int Type; +}; +template<> +struct ElementTypeTrait +{ + typedef int Type; +}; +template<> +struct ElementTypeTrait +{ + typedef int Type; +}; +template<> +struct ElementTypeTrait +{ + typedef int Type; +}; + +template<> +struct ElementTypeTrait +{ + typedef uint Type; +}; +template<> +struct ElementTypeTrait +{ + typedef uint Type; +}; +template<> +struct ElementTypeTrait +{ + typedef uint Type; +}; +template<> +struct ElementTypeTrait +{ + typedef uint Type; +}; + +template<> +struct ElementTypeTrait +{ + typedef float Type; +}; +template<> +struct ElementTypeTrait +{ + typedef float Type; +}; +template<> +struct ElementTypeTrait +{ + typedef float Type; +}; +template<> +struct ElementTypeTrait +{ + typedef float Type; +}; + +template<> +struct ElementTypeTrait +{ + typedef double Type; +}; +template<> +struct ElementTypeTrait +{ + typedef double Type; +}; +template<> +struct ElementTypeTrait +{ + typedef double Type; +}; +template<> +struct ElementTypeTrait +{ + typedef double Type; +}; // Matrix -template -struct ElementTypeTrait > -{ - typedef T Type; +template +struct ElementTypeTrait> +{ + typedef T Type; }; -// Scalar -template +// Scalar +template __device__ T _waveReduceScalar(WarpMask mask, T val) { const int offsetSize = _waveCalcPow2Offset(mask); if (offsetSize > 0) { - // Fast path O(log2(activeLanes)) + // Fast path O(log2(activeLanes)) for (int offset = offsetSize >> 1; offset > 0; offset >>= 1) { val = INTF::doOp(val, __shfl_xor_sync(mask, val, offset)); @@ -1600,9 +2419,9 @@ __device__ T _waveReduceScalar(WarpMask mask, T val) while (remaining) { const int laneBit = remaining & -remaining; - // Get the sourceLane + // Get the sourceLane const int srcLane = __ffs(laneBit) - 1; - // Broadcast (can also broadcast to self) + // Broadcast (can also broadcast to self) result = INTF::doOp(result, __shfl_sync(mask, val, srcLane)); remaining &= ~laneBit; } @@ -1613,13 +2432,13 @@ __device__ T _waveReduceScalar(WarpMask mask, T val) // Multiple values -template +template __device__ void _waveReduceMultiple(WarpMask mask, T* val) { const int offsetSize = _waveCalcPow2Offset(mask); if (offsetSize > 0) { - // Fast path O(log2(activeLanes)) + // Fast path O(log2(activeLanes)) for (int offset = offsetSize >> 1; offset > 0; offset >>= 1) { for (size_t i = 0; i < COUNT; ++i) @@ -1638,14 +2457,14 @@ __device__ void _waveReduceMultiple(WarpMask mask, T* val) originalVal[i] = v; val[i] = INTF::getInitial(v); } - + int remaining = mask; while (remaining) { const int laneBit = remaining & -remaining; - // Get the sourceLane + // Get the sourceLane const int srcLane = __ffs(laneBit) - 1; - // Broadcast (can also broadcast to self) + // Broadcast (can also broadcast to self) for (size_t i = 0; i < COUNT; ++i) { val[i] = INTF::doOp(val[i], __shfl_sync(mask, originalVal[i], srcLane)); @@ -1655,99 +2474,182 @@ __device__ void _waveReduceMultiple(WarpMask mask, T* val) } } -template +template __device__ void _waveReduceMultiple(WarpMask mask, T* val) { - typedef typename ElementTypeTrait::Type ElemType; + typedef typename ElementTypeTrait::Type ElemType; _waveReduceMultiple(mask, (ElemType*)val); } -template -__inline__ __device__ T _waveOr(WarpMask mask, T val) { return _waveReduceScalar, T>(mask, val); } +template +__inline__ __device__ T _waveOr(WarpMask mask, T val) +{ + return _waveReduceScalar, T>(mask, val); +} -template -__inline__ __device__ T _waveAnd(WarpMask mask, T val) { return _waveReduceScalar, T>(mask, val); } +template +__inline__ __device__ T _waveAnd(WarpMask mask, T val) +{ + return _waveReduceScalar, T>(mask, val); +} -template -__inline__ __device__ T _waveXor(WarpMask mask, T val) { return _waveReduceScalar, T>(mask, val); } +template +__inline__ __device__ T _waveXor(WarpMask mask, T val) +{ + return _waveReduceScalar, T>(mask, val); +} -template -__inline__ __device__ T _waveProduct(WarpMask mask, T val) { return _waveReduceScalar, T>(mask, val); } +template +__inline__ __device__ T _waveProduct(WarpMask mask, T val) +{ + return _waveReduceScalar, T>(mask, val); +} -template -__inline__ __device__ T _waveSum(WarpMask mask, T val) { return _waveReduceScalar, T>(mask, val); } +template +__inline__ __device__ T _waveSum(WarpMask mask, T val) +{ + return _waveReduceScalar, T>(mask, val); +} -template -__inline__ __device__ T _waveMin(WarpMask mask, T val) { return _waveReduceScalar, T>(mask, val); } +template +__inline__ __device__ T _waveMin(WarpMask mask, T val) +{ + return _waveReduceScalar, T>(mask, val); +} -template -__inline__ __device__ T _waveMax(WarpMask mask, T val) { return _waveReduceScalar, T>(mask, val); } +template +__inline__ __device__ T _waveMax(WarpMask mask, T val) +{ + return _waveReduceScalar, T>(mask, val); +} // Fast-path specializations when CUDA warp reduce operators are available #if __CUDA_ARCH__ >= 800 // 8.x or higher template<> -__inline__ __device__ unsigned _waveOr(WarpMask mask, unsigned val) { return __reduce_or_sync(mask, val); } +__inline__ __device__ unsigned _waveOr(WarpMask mask, unsigned val) +{ + return __reduce_or_sync(mask, val); +} template<> -__inline__ __device__ unsigned _waveAnd(WarpMask mask, unsigned val) { return __reduce_and_sync(mask, val); } +__inline__ __device__ unsigned _waveAnd(WarpMask mask, unsigned val) +{ + return __reduce_and_sync(mask, val); +} template<> -__inline__ __device__ unsigned _waveXor(WarpMask mask, unsigned val) { return __reduce_xor_sync(mask, val); } +__inline__ __device__ unsigned _waveXor(WarpMask mask, unsigned val) +{ + return __reduce_xor_sync(mask, val); +} template<> -__inline__ __device__ unsigned _waveSum(WarpMask mask, unsigned val) { return __reduce_add_sync(mask, val); } +__inline__ __device__ unsigned _waveSum(WarpMask mask, unsigned val) +{ + return __reduce_add_sync(mask, val); +} template<> -__inline__ __device__ int _waveSum(WarpMask mask, int val) { return __reduce_add_sync(mask, val); } +__inline__ __device__ int _waveSum(WarpMask mask, int val) +{ + return __reduce_add_sync(mask, val); +} template<> -__inline__ __device__ unsigned _waveMin(WarpMask mask, unsigned val) { return __reduce_min_sync(mask, val); } +__inline__ __device__ unsigned _waveMin(WarpMask mask, unsigned val) +{ + return __reduce_min_sync(mask, val); +} template<> -__inline__ __device__ int _waveMin(WarpMask mask, int val) { return __reduce_min_sync(mask, val); } +__inline__ __device__ int _waveMin(WarpMask mask, int val) +{ + return __reduce_min_sync(mask, val); +} template<> -__inline__ __device__ unsigned _waveMax(WarpMask mask, unsigned val) { return __reduce_max_sync(mask, val); } +__inline__ __device__ unsigned _waveMax(WarpMask mask, unsigned val) +{ + return __reduce_max_sync(mask, val); +} template<> -__inline__ __device__ int _waveMax(WarpMask mask, int val) { return __reduce_max_sync(mask, val); } +__inline__ __device__ int _waveMax(WarpMask mask, int val) +{ + return __reduce_max_sync(mask, val); +} #endif // Multiple -template -__inline__ __device__ T _waveOrMultiple(WarpMask mask, T val) { typedef typename ElementTypeTrait::Type ElemType; _waveReduceMultiple >(mask, &val); return val; } +template +__inline__ __device__ T _waveOrMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _waveReduceMultiple>(mask, &val); + return val; +} -template -__inline__ __device__ T _waveAndMultiple(WarpMask mask, T val) { typedef typename ElementTypeTrait::Type ElemType; _waveReduceMultiple >(mask, &val); return val; } +template +__inline__ __device__ T _waveAndMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _waveReduceMultiple>(mask, &val); + return val; +} -template -__inline__ __device__ T _waveXorMultiple(WarpMask mask, T val) { typedef typename ElementTypeTrait::Type ElemType; _waveReduceMultiple >(mask, &val); return val; } +template +__inline__ __device__ T _waveXorMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _waveReduceMultiple>(mask, &val); + return val; +} -template -__inline__ __device__ T _waveProductMultiple(WarpMask mask, T val) { typedef typename ElementTypeTrait::Type ElemType; _waveReduceMultiple >(mask, &val); return val; } +template +__inline__ __device__ T _waveProductMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _waveReduceMultiple>(mask, &val); + return val; +} -template -__inline__ __device__ T _waveSumMultiple(WarpMask mask, T val) { typedef typename ElementTypeTrait::Type ElemType; _waveReduceMultiple >(mask, &val); return val; } +template +__inline__ __device__ T _waveSumMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _waveReduceMultiple>(mask, &val); + return val; +} -template -__inline__ __device__ T _waveMinMultiple(WarpMask mask, T val) { typedef typename ElementTypeTrait::Type ElemType; _waveReduceMultiple >(mask, &val); return val; } +template +__inline__ __device__ T _waveMinMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _waveReduceMultiple>(mask, &val); + return val; +} -template -__inline__ __device__ T _waveMaxMultiple(WarpMask mask, T val) { typedef typename ElementTypeTrait::Type ElemType; _waveReduceMultiple >(mask, &val); return val; } +template +__inline__ __device__ T _waveMaxMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _waveReduceMultiple>(mask, &val); + return val; +} -template -__inline__ __device__ bool _waveAllEqual(WarpMask mask, T val) +template +__inline__ __device__ bool _waveAllEqual(WarpMask mask, T val) { int pred; __match_all_sync(mask, val, &pred); return pred != 0; } -template -__inline__ __device__ bool _waveAllEqualMultiple(WarpMask mask, T inVal) +template +__inline__ __device__ bool _waveAllEqualMultiple(WarpMask mask, T inVal) { typedef typename ElementTypeTrait::Type ElemType; const size_t count = sizeof(T) / sizeof(ElemType); @@ -1764,15 +2666,15 @@ __inline__ __device__ bool _waveAllEqualMultiple(WarpMask mask, T inVal) return true; } -template -__inline__ __device__ T _waveReadFirst(WarpMask mask, T val) +template +__inline__ __device__ T _waveReadFirst(WarpMask mask, T val) { const int lowestLaneId = __ffs(mask) - 1; - return __shfl_sync(mask, val, lowestLaneId); + return __shfl_sync(mask, val, lowestLaneId); } -template -__inline__ __device__ T _waveReadFirstMultiple(WarpMask mask, T inVal) +template +__inline__ __device__ T _waveReadFirstMultiple(WarpMask mask, T inVal) { typedef typename ElementTypeTrait::Type ElemType; const size_t count = sizeof(T) / sizeof(ElemType); @@ -1782,12 +2684,12 @@ __inline__ __device__ T _waveReadFirstMultiple(WarpMask mask, T inVal) const int lowestLaneId = __ffs(mask) - 1; for (size_t i = 0; i < count; ++i) { - dst[i] = __shfl_sync(mask, src[i], lowestLaneId); + dst[i] = __shfl_sync(mask, src[i], lowestLaneId); } return outVal; } -template +template __inline__ __device__ T _waveShuffleMultiple(WarpMask mask, T inVal, int lane) { typedef typename ElementTypeTrait::Type ElemType; @@ -1797,27 +2699,27 @@ __inline__ __device__ T _waveShuffleMultiple(WarpMask mask, T inVal, int lane) ElemType* dst = (ElemType*)&outVal; for (size_t i = 0; i < count; ++i) { - dst[i] = __shfl_sync(mask, src[i], lane); + dst[i] = __shfl_sync(mask, src[i], lane); } return outVal; } -// Scalar +// Scalar -// Invertable means that when we get to the end of the reduce, we can remove val (to make exclusive), using -// the inverse of the op. -template +// Invertable means that when we get to the end of the reduce, we can remove val (to make +// exclusive), using the inverse of the op. +template __device__ T _wavePrefixInvertableScalar(WarpMask mask, T val) { const int offsetSize = _waveCalcPow2Offset(mask); - + const int laneId = _getLaneId(); T result; if (offsetSize > 0) - { + { // Sum is calculated inclusive of this lanes value result = val; - for (int i = 1; i < offsetSize; i += i) + for (int i = 1; i < offsetSize; i += i) { const T readVal = __shfl_up_sync(mask, result, i, offsetSize); if (laneId >= i) @@ -1828,7 +2730,7 @@ __device__ T _wavePrefixInvertableScalar(WarpMask mask, T val) // Remove val from the result, by applyin inverse result = INTF::doInverse(result, val); } - else + else { result = INTF::getInitial(val); if (!_waveIsSingleLane(mask)) @@ -1837,9 +2739,9 @@ __device__ T _wavePrefixInvertableScalar(WarpMask mask, T val) while (remaining) { const int laneBit = remaining & -remaining; - // Get the sourceLane + // Get the sourceLane const int srcLane = __ffs(laneBit) - 1; - // Broadcast (can also broadcast to self) + // Broadcast (can also broadcast to self) const T readValue = __shfl_sync(mask, val, srcLane); // Only accumulate if srcLane is less than this lane if (srcLane < laneId) @@ -1848,27 +2750,28 @@ __device__ T _wavePrefixInvertableScalar(WarpMask mask, T val) } remaining &= ~laneBit; } - } + } } return result; } - + // This implementation separately tracks the value to be propogated, and the value -// that is the final result -template +// that is the final result +template __device__ T _wavePrefixScalar(WarpMask mask, T val) { const int offsetSize = _waveCalcPow2Offset(mask); - + const int laneId = _getLaneId(); - T result = INTF::getInitial(val); + T result = INTF::getInitial(val); if (offsetSize > 0) - { + { // For transmitted value we will do it inclusively with this lanes value - // For the result we do not include the lanes value. This means an extra multiply for each iteration - // but means we don't need to have a divide at the end and also removes overflow issues in that scenario. - for (int i = 1; i < offsetSize; i += i) + // For the result we do not include the lanes value. This means an extra multiply for each + // iteration but means we don't need to have a divide at the end and also removes overflow + // issues in that scenario. + for (int i = 1; i < offsetSize; i += i) { const T readVal = __shfl_up_sync(mask, val, i, offsetSize); if (laneId >= i) @@ -1878,7 +2781,7 @@ __device__ T _wavePrefixScalar(WarpMask mask, T val) } } } - else + else { if (!_waveIsSingleLane(mask)) { @@ -1886,9 +2789,9 @@ __device__ T _wavePrefixScalar(WarpMask mask, T val) while (remaining) { const int laneBit = remaining & -remaining; - // Get the sourceLane + // Get the sourceLane const int srcLane = __ffs(laneBit) - 1; - // Broadcast (can also broadcast to self) + // Broadcast (can also broadcast to self) const T readValue = __shfl_sync(mask, val, srcLane); // Only accumulate if srcLane is less than this lane if (srcLane < laneId) @@ -1903,51 +2806,51 @@ __device__ T _wavePrefixScalar(WarpMask mask, T val) } -template +template __device__ T _waveOpCopy(T* dst, const T* src) { for (size_t j = 0; j < COUNT; ++j) { dst[j] = src[j]; } -} +} -template +template __device__ T _waveOpDoInverse(T* inOut, const T* val) { for (size_t j = 0; j < COUNT; ++j) { inOut[j] = INTF::doInverse(inOut[j], val[j]); } -} +} -template +template __device__ T _waveOpSetInitial(T* out, const T* val) { for (size_t j = 0; j < COUNT; ++j) { out[j] = INTF::getInitial(val[j]); } -} +} -template +template __device__ T _wavePrefixInvertableMultiple(WarpMask mask, T* val) { const int offsetSize = _waveCalcPow2Offset(mask); - + const int laneId = _getLaneId(); T originalVal[COUNT]; _waveOpCopy(originalVal, val); - + if (offsetSize > 0) - { + { // Sum is calculated inclusive of this lanes value - for (int i = 1; i < offsetSize; i += i) + for (int i = 1; i < offsetSize; i += i) { // TODO(JS): Note that here I don't split the laneId outside so it's only tested once. - // This may be better but it would also mean that there would be shfl between lanes - // that are on different (albeit identical) instructions. So this seems more likely to + // This may be better but it would also mean that there would be shfl between lanes + // that are on different (albeit identical) instructions. So this seems more likely to // work as expected with everything in lock step. for (size_t j = 0; j < COUNT; ++j) { @@ -1961,7 +2864,7 @@ __device__ T _wavePrefixInvertableMultiple(WarpMask mask, T* val) // Remove originalVal from the result, by applyin inverse _waveOpDoInverse(val, originalVal); } - else + else { _waveOpSetInitial(val, val); if (!_waveIsSingleLane(mask)) @@ -1970,12 +2873,12 @@ __device__ T _wavePrefixInvertableMultiple(WarpMask mask, T* val) while (remaining) { const int laneBit = remaining & -remaining; - // Get the sourceLane + // Get the sourceLane const int srcLane = __ffs(laneBit) - 1; - + for (size_t j = 0; j < COUNT; ++j) { - // Broadcast (can also broadcast to self) + // Broadcast (can also broadcast to self) const T readValue = __shfl_sync(mask, originalVal[j], srcLane); // Only accumulate if srcLane is less than this lane if (srcLane < laneId) @@ -1985,27 +2888,28 @@ __device__ T _wavePrefixInvertableMultiple(WarpMask mask, T* val) remaining &= ~laneBit; } } - } + } } } - -template + +template __device__ T _wavePrefixMultiple(WarpMask mask, T* val) { const int offsetSize = _waveCalcPow2Offset(mask); - + const int laneId = _getLaneId(); - + T work[COUNT]; _waveOpCopy(work, val); _waveOpSetInitial(val, val); - + if (offsetSize > 0) - { + { // For transmitted value we will do it inclusively with this lanes value - // For the result we do not include the lanes value. This means an extra op for each iteration - // but means we don't need to have a divide at the end and also removes overflow issues in that scenario. - for (int i = 1; i < offsetSize; i += i) + // For the result we do not include the lanes value. This means an extra op for each + // iteration but means we don't need to have a divide at the end and also removes overflow + // issues in that scenario. + for (int i = 1; i < offsetSize; i += i) { for (size_t j = 0; j < COUNT; ++j) { @@ -2013,12 +2917,12 @@ __device__ T _wavePrefixMultiple(WarpMask mask, T* val) if (laneId >= i) { work[j] = INTF::doOp(work[j], readVal); - val[j] = INTF::doOp(val[j], readVal); + val[j] = INTF::doOp(val[j], readVal); } } } } - else + else { if (!_waveIsSingleLane(mask)) { @@ -2026,12 +2930,12 @@ __device__ T _wavePrefixMultiple(WarpMask mask, T* val) while (remaining) { const int laneBit = remaining & -remaining; - // Get the sourceLane + // Get the sourceLane const int srcLane = __ffs(laneBit) - 1; - + for (size_t j = 0; j < COUNT; ++j) { - // Broadcast (can also broadcast to self) + // Broadcast (can also broadcast to self) const T readValue = __shfl_sync(mask, work[j], srcLane); // Only accumulate if srcLane is less than this lane if (srcLane < laneId) @@ -2045,71 +2949,96 @@ __device__ T _wavePrefixMultiple(WarpMask mask, T* val) } } -template -__inline__ __device__ T _wavePrefixProduct(WarpMask mask, T val) { return _wavePrefixScalar, T>(mask, val); } - -template -__inline__ __device__ T _wavePrefixSum(WarpMask mask, T val) { return _wavePrefixInvertableScalar, T>(mask, val); } - -template -__inline__ __device__ T _wavePrefixXor(WarpMask mask, T val) { return _wavePrefixInvertableScalar, T>(mask, val); } - -template -__inline__ __device__ T _wavePrefixOr(WarpMask mask, T val) { return _wavePrefixScalar, T>(mask, val); } - -template -__inline__ __device__ T _wavePrefixAnd(WarpMask mask, T val) { return _wavePrefixScalar, T>(mask, val); } - - -template -__inline__ __device__ T _wavePrefixProductMultiple(WarpMask mask, T val) -{ - typedef typename ElementTypeTrait::Type ElemType; - _wavePrefixInvertableMultiple, ElemType, sizeof(T) / sizeof(ElemType)>(mask, (ElemType*)&val); +template +__inline__ __device__ T _wavePrefixProduct(WarpMask mask, T val) +{ + return _wavePrefixScalar, T>(mask, val); +} + +template +__inline__ __device__ T _wavePrefixSum(WarpMask mask, T val) +{ + return _wavePrefixInvertableScalar, T>(mask, val); +} + +template +__inline__ __device__ T _wavePrefixXor(WarpMask mask, T val) +{ + return _wavePrefixInvertableScalar, T>(mask, val); +} + +template +__inline__ __device__ T _wavePrefixOr(WarpMask mask, T val) +{ + return _wavePrefixScalar, T>(mask, val); +} + +template +__inline__ __device__ T _wavePrefixAnd(WarpMask mask, T val) +{ + return _wavePrefixScalar, T>(mask, val); +} + + +template +__inline__ __device__ T _wavePrefixProductMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _wavePrefixInvertableMultiple, ElemType, sizeof(T) / sizeof(ElemType)>( + mask, + (ElemType*)&val); return val; } -template -__inline__ __device__ T _wavePrefixSumMultiple(WarpMask mask, T val) -{ - typedef typename ElementTypeTrait::Type ElemType; - _wavePrefixInvertableMultiple, ElemType, sizeof(T) / sizeof(ElemType)>(mask, (ElemType*)&val); +template +__inline__ __device__ T _wavePrefixSumMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _wavePrefixInvertableMultiple, ElemType, sizeof(T) / sizeof(ElemType)>( + mask, + (ElemType*)&val); return val; } -template -__inline__ __device__ T _wavePrefixXorMultiple(WarpMask mask, T val) -{ - typedef typename ElementTypeTrait::Type ElemType; - _wavePrefixInvertableMultiple, ElemType, sizeof(T) / sizeof(ElemType)>(mask, (ElemType*)&val); +template +__inline__ __device__ T _wavePrefixXorMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _wavePrefixInvertableMultiple, ElemType, sizeof(T) / sizeof(ElemType)>( + mask, + (ElemType*)&val); return val; } -template -__inline__ __device__ T _wavePrefixOrMultiple(WarpMask mask, T val) -{ - typedef typename ElementTypeTrait::Type ElemType; - _wavePrefixMultiple, ElemType, sizeof(T) / sizeof(ElemType)>(mask, (ElemType*)&val); +template +__inline__ __device__ T _wavePrefixOrMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _wavePrefixMultiple, ElemType, sizeof(T) / sizeof(ElemType)>( + mask, + (ElemType*)&val); return val; } -template -__inline__ __device__ T _wavePrefixAndMultiple(WarpMask mask, T val) -{ - typedef typename ElementTypeTrait::Type ElemType; - _wavePrefixMultiple, ElemType, sizeof(T) / sizeof(ElemType)>(mask, (ElemType*)&val); +template +__inline__ __device__ T _wavePrefixAndMultiple(WarpMask mask, T val) +{ + typedef typename ElementTypeTrait::Type ElemType; + _wavePrefixMultiple, ElemType, sizeof(T) / sizeof(ElemType)>( + mask, + (ElemType*)&val); return val; } -template -__inline__ __device__ uint4 _waveMatchScalar(WarpMask mask, T val) +template +__inline__ __device__ uint4 _waveMatchScalar(WarpMask mask, T val) { int pred; return make_uint4(__match_all_sync(mask, val, &pred), 0, 0, 0); } -template -__inline__ __device__ uint4 _waveMatchMultiple(WarpMask mask, const T& inVal) +template +__inline__ __device__ uint4 _waveMatchMultiple(WarpMask mask, const T& inVal) { typedef typename ElementTypeTrait::Type ElemType; const size_t count = sizeof(T) / sizeof(ElemType); @@ -2123,7 +3052,7 @@ __inline__ __device__ uint4 _waveMatchMultiple(WarpMask mask, const T& inVal) return make_uint4(matchBits, 0, 0, 0); } -__device__ uint getAt(dim3 a, int b) +__device__ uint getAt(dim3 a, int b) { SLANG_PRELUDE_ASSERT(b >= 0 && b < 3); return (&a.x)[b]; @@ -2146,8 +3075,9 @@ __inline__ __device__ TResult slang_bit_cast(TInput val) /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* Type that defines the uniform entry point params. The actual content of this type is dependent on the entry point parameters, and can be -found via reflection or defined such that it matches the shader appropriately. +/* Type that defines the uniform entry point params. The actual content of this type is dependent on +the entry point parameters, and can be found via reflection or defined such that it matches the +shader appropriately. */ struct UniformEntryPointParams; struct UniformState; @@ -2157,28 +3087,29 @@ struct UniformState; struct RayDesc { float3 Origin; - float TMin; + float TMin; float3 Direction; - float TMax; + float TMax; }; -static __forceinline__ __device__ -void *unpackOptiXRayPayloadPointer(uint32_t i0, uint32_t i1) +static __forceinline__ __device__ void* unpackOptiXRayPayloadPointer(uint32_t i0, uint32_t i1) { const uint64_t uptr = static_cast(i0) << 32 | i1; - void* ptr = reinterpret_cast(uptr); + void* ptr = reinterpret_cast(uptr); return ptr; } -static __forceinline__ __device__ -void packOptiXRayPayloadPointer(void* ptr, uint32_t& i0, uint32_t& i1) +static __forceinline__ __device__ void packOptiXRayPayloadPointer( + void* ptr, + uint32_t& i0, + uint32_t& i1) { const uint64_t uptr = reinterpret_cast(ptr); i0 = uptr >> 32; i1 = uptr & 0x00000000ffffffff; } -static __forceinline__ __device__ void *getOptiXRayPayloadPtr() +static __forceinline__ __device__ void* getOptiXRayPayloadPtr() { const uint32_t u0 = optixGetPayload_0(); const uint32_t u1 = optixGetPayload_1(); @@ -2186,7 +3117,7 @@ static __forceinline__ __device__ void *getOptiXRayPayloadPtr() } template -__forceinline__ __device__ void *traceOptiXRay( +__forceinline__ __device__ void* traceOptiXRay( OptixTraversableHandle AccelerationStructure, uint32_t RayFlags, uint32_t InstanceInclusionMask, @@ -2194,8 +3125,8 @@ __forceinline__ __device__ void *traceOptiXRay( uint32_t MultiplierForGeometryContributionToHitGroupIndex, uint32_t MissShaderIndex, RayDesc Ray, - T *Payload -) { + T* Payload) +{ uint32_t r0, r1; packOptiXRayPayloadPointer((void*)Payload, r0, r1); optixTrace( @@ -2210,8 +3141,8 @@ __forceinline__ __device__ void *traceOptiXRay( RayContributionToHitGroupIndex, MultiplierForGeometryContributionToHitGroupIndex, MissShaderIndex, - r0, r1 - ); + r0, + r1); } #endif @@ -2256,7 +3187,8 @@ struct TensorView template __device__ T* data_ptr_at(uint4 index) { - uint64_t offset = strides[0] * index.x + strides[1] * index.y + strides[2] * index.z + strides[3] * index.w; + uint64_t offset = strides[0] * index.x + strides[1] * index.y + strides[2] * index.z + + strides[3] * index.w; return reinterpret_cast(data + offset); } @@ -2294,22 +3226,28 @@ struct TensorView template __device__ T& load(uint3 index) { - return *reinterpret_cast(data + strides[0] * index.x + strides[1] * index.y + strides[2] * index.z); + return *reinterpret_cast( + data + strides[0] * index.x + strides[1] * index.y + strides[2] * index.z); } template __device__ T& load(uint32_t x, uint32_t y, uint32_t z, uint32_t w) { - return *reinterpret_cast(data + strides[0] * x + strides[1] * y + strides[2] * z + strides[3] * w); + return *reinterpret_cast( + data + strides[0] * x + strides[1] * y + strides[2] * z + strides[3] * w); } template __device__ T& load(uint4 index) { - return *reinterpret_cast(data + strides[0] * index.x + strides[1] * index.y + strides[2] * index.z + strides[3] * index.w); + return *reinterpret_cast( + data + strides[0] * index.x + strides[1] * index.y + strides[2] * index.z + + strides[3] * index.w); } template __device__ T& load(uint32_t i0, uint32_t i1, uint32_t i2, uint32_t i3, uint32_t i4) { - return *reinterpret_cast(data + strides[0] * i0 + strides[1] * i1 + strides[2] * i2 + strides[3] * i3 + strides[4] * i4); + return *reinterpret_cast( + data + strides[0] * i0 + strides[1] * i1 + strides[2] * i2 + strides[3] * i3 + + strides[4] * i4); } // Generic version of load @@ -2347,7 +3285,8 @@ struct TensorView template __device__ void store(uint3 index, T val) { - *reinterpret_cast(data + strides[0] * index.x + strides[1] * index.y + strides[2] * index.z) = val; + *reinterpret_cast( + data + strides[0] * index.x + strides[1] * index.y + strides[2] * index.z) = val; } template __device__ void store(uint32_t x, uint32_t y, uint32_t z, uint32_t w, T val) @@ -2358,12 +3297,16 @@ struct TensorView template __device__ void store(uint4 index, T val) { - *reinterpret_cast(data + strides[0] * index.x + strides[1] * index.y + strides[2] * index.z + strides[3] * index.w) = val; + *reinterpret_cast( + data + strides[0] * index.x + strides[1] * index.y + strides[2] * index.z + + strides[3] * index.w) = val; } template __device__ void store(uint32_t i0, uint32_t i1, uint32_t i2, uint32_t i3, uint32_t i4, T val) { - *reinterpret_cast(data + strides[0] * i0 + strides[1] * i1 + strides[2] * i2 + strides[3] * i3 + strides[4] * i4) = val; + *reinterpret_cast( + data + strides[0] * i0 + strides[1] * i1 + strides[2] * i2 + strides[3] * i3 + + strides[4] * i4) = val; } // Generic version diff --git a/prelude/slang-hlsl-prelude.h b/prelude/slang-hlsl-prelude.h index d892f228c..8e77201f9 100644 --- a/prelude/slang-hlsl-prelude.h +++ b/prelude/slang-hlsl-prelude.h @@ -3,6 +3,6 @@ #endif #ifndef __DXC_VERSION_MAJOR - // warning X3557: loop doesn't seem to do anything, forcing loop to unroll - #pragma warning(disable: 3557) +// warning X3557: loop doesn't seem to do anything, forcing loop to unroll +#pragma warning(disable : 3557) #endif diff --git a/prelude/slang-llvm.h b/prelude/slang-llvm.h index b41380581..e0bbbd14a 100644 --- a/prelude/slang-llvm.h +++ b/prelude/slang-llvm.h @@ -1,46 +1,54 @@ #ifndef SLANG_LLVM_H #define SLANG_LLVM_H -// TODO(JS): +// TODO(JS): // Disable exception declspecs, as not supported on LLVM without some extra options. // We could enable with `-fms-extensions` #define SLANG_DISABLE_EXCEPTIONS 1 #ifndef SLANG_PRELUDE_ASSERT -# ifdef SLANG_PRELUDE_ENABLE_ASSERT +#ifdef SLANG_PRELUDE_ENABLE_ASSERT extern "C" void assertFailure(const char* msg); -# define SLANG_PRELUDE_EXPECT(VALUE, MSG) if(VALUE) {} else assertFailure("assertion failed: '" MSG "'") -# define SLANG_PRELUDE_ASSERT(VALUE) SLANG_PRELUDE_EXPECT(VALUE, #VALUE) -# else // SLANG_PRELUDE_ENABLE_ASSERT -# define SLANG_PRELUDE_EXPECT(VALUE, MSG) -# define SLANG_PRELUDE_ASSERT(x) -# endif // SLANG_PRELUDE_ENABLE_ASSERT +#define SLANG_PRELUDE_EXPECT(VALUE, MSG) \ + if (VALUE) \ + { \ + } \ + else \ + assertFailure("assertion failed: '" MSG "'") +#define SLANG_PRELUDE_ASSERT(VALUE) SLANG_PRELUDE_EXPECT(VALUE, #VALUE) +#else // SLANG_PRELUDE_ENABLE_ASSERT +#define SLANG_PRELUDE_EXPECT(VALUE, MSG) +#define SLANG_PRELUDE_ASSERT(x) +#endif // SLANG_PRELUDE_ENABLE_ASSERT #endif /* -Taken from stddef.h +Taken from stddef.h */ typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef __SIZE_TYPE__ size_t; typedef __SIZE_TYPE__ rsize_t; -//typedef __WCHAR_TYPE__ wchar_t; +// typedef __WCHAR_TYPE__ wchar_t; #if defined(__need_NULL) #undef NULL #ifdef __cplusplus -# if !defined(__MINGW32__) && !defined(_MSC_VER) -# define NULL __null -# else -# define NULL 0 -# endif +#if !defined(__MINGW32__) && !defined(_MSC_VER) +#define NULL __null #else -# define NULL ((void*)0) +#define NULL 0 +#endif +#else +#define NULL ((void*)0) #endif #ifdef __cplusplus #if defined(_MSC_EXTENSIONS) && defined(_NATIVE_NULLPTR_SUPPORTED) -namespace std { typedef decltype(nullptr) nullptr_t; } +namespace std +{ +typedef decltype(nullptr) nullptr_t; +} using ::std::nullptr_t; #endif #endif @@ -49,18 +57,18 @@ using ::std::nullptr_t; /* -The following are taken verbatim from stdint.h from Clang in LLVM. Only 8/16/32/64 types are needed. +The following are taken verbatim from stdint.h from Clang in LLVM. Only 8/16/32/64 types are needed. */ // LLVM/Clang types such that we can use LLVM/Clang without headers for C++ output from Slang #ifdef __INT64_TYPE__ -# ifndef __int8_t_defined /* glibc sys/types.h also defines int64_t*/ +#ifndef __int8_t_defined /* glibc sys/types.h also defines int64_t*/ typedef __INT64_TYPE__ int64_t; -# endif /* __int8_t_defined */ +#endif /* __int8_t_defined */ typedef __UINT64_TYPE__ uint64_t; -# define __int_least64_t int64_t -# define __uint_least64_t uint64_t +#define __int_least64_t int64_t +#define __uint_least64_t uint64_t #endif /* __INT64_TYPE__ */ #ifdef __int_least64_t @@ -72,17 +80,17 @@ typedef __uint_least64_t uint_fast64_t; #ifdef __INT32_TYPE__ -# ifndef __int8_t_defined /* glibc sys/types.h also defines int32_t*/ +#ifndef __int8_t_defined /* glibc sys/types.h also defines int32_t*/ typedef __INT32_TYPE__ int32_t; -# endif /* __int8_t_defined */ +#endif /* __int8_t_defined */ -# ifndef __uint32_t_defined /* more glibc compatibility */ -# define __uint32_t_defined +#ifndef __uint32_t_defined /* more glibc compatibility */ +#define __uint32_t_defined typedef __UINT32_TYPE__ uint32_t; -# endif /* __uint32_t_defined */ +#endif /* __uint32_t_defined */ -# define __int_least32_t int32_t -# define __uint_least32_t uint32_t +#define __int_least32_t int32_t +#define __uint_least32_t uint32_t #endif /* __INT32_TYPE__ */ #ifdef __int_least32_t @@ -97,8 +105,8 @@ typedef __uint_least32_t uint_fast32_t; typedef __INT16_TYPE__ int16_t; #endif /* __int8_t_defined */ typedef __UINT16_TYPE__ uint16_t; -# define __int_least16_t int16_t -# define __uint_least16_t uint16_t +#define __int_least16_t int16_t +#define __uint_least16_t uint16_t #endif /* __INT16_TYPE__ */ #ifdef __int_least16_t @@ -109,12 +117,12 @@ typedef __uint_least16_t uint_fast16_t; #endif /* __int_least16_t */ #ifdef __INT8_TYPE__ -#ifndef __int8_t_defined /* glibc sys/types.h also defines int8_t*/ +#ifndef __int8_t_defined /* glibc sys/types.h also defines int8_t*/ typedef __INT8_TYPE__ int8_t; #endif /* __int8_t_defined */ typedef __UINT8_TYPE__ uint8_t; -# define __int_least8_t int8_t -# define __uint_least8_t uint8_t +#define __int_least8_t int8_t +#define __uint_least8_t uint8_t #endif /* __INT8_TYPE__ */ #ifdef __int_least8_t @@ -126,12 +134,12 @@ typedef __uint_least8_t uint_fast8_t; /* prevent glibc sys/types.h from defining conflicting types */ #ifndef __int8_t_defined -# define __int8_t_defined +#define __int8_t_defined #endif /* __int8_t_defined */ /* C99 7.18.1.4 Integer types capable of holding object pointers. */ -#define __stdint_join3(a,b,c) a ## b ## c +#define __stdint_join3(a, b, c) a##b##c #ifndef _INTPTR_T #ifndef __intptr_t_defined @@ -148,7 +156,7 @@ typedef __UINTPTR_TYPE__ uintptr_t; /* C99 7.18.1.5 Greatest-width integer types. */ -typedef __INTMAX_TYPE__ intmax_t; +typedef __INTMAX_TYPE__ intmax_t; typedef __UINTMAX_TYPE__ uintmax_t; /* C99 7.18.4 Macros for minimum-width integer constants. @@ -168,82 +176,82 @@ typedef __UINTMAX_TYPE__ uintmax_t; * claims of the C standard (see C++ 18.3.1p2, [cstdint.syn]). */ -#define __int_c_join(a, b) a ## b +#define __int_c_join(a, b) a##b #define __int_c(v, suffix) __int_c_join(v, suffix) #define __uint_c(v, suffix) __int_c_join(v##U, suffix) #ifdef __INT64_TYPE__ -# ifdef __INT64_C_SUFFIX__ -# define __int64_c_suffix __INT64_C_SUFFIX__ -# else -# undef __int64_c_suffix -# endif /* __INT64_C_SUFFIX__ */ +#ifdef __INT64_C_SUFFIX__ +#define __int64_c_suffix __INT64_C_SUFFIX__ +#else +#undef __int64_c_suffix +#endif /* __INT64_C_SUFFIX__ */ #endif /* __INT64_TYPE__ */ #ifdef __int_least64_t -# ifdef __int64_c_suffix -# define INT64_C(v) __int_c(v, __int64_c_suffix) -# define UINT64_C(v) __uint_c(v, __int64_c_suffix) -# else -# define INT64_C(v) v -# define UINT64_C(v) v ## U -# endif /* __int64_c_suffix */ +#ifdef __int64_c_suffix +#define INT64_C(v) __int_c(v, __int64_c_suffix) +#define UINT64_C(v) __uint_c(v, __int64_c_suffix) +#else +#define INT64_C(v) v +#define UINT64_C(v) v##U +#endif /* __int64_c_suffix */ #endif /* __int_least64_t */ #ifdef __INT32_TYPE__ -# ifdef __INT32_C_SUFFIX__ -# define __int32_c_suffix __INT32_C_SUFFIX__ +#ifdef __INT32_C_SUFFIX__ +#define __int32_c_suffix __INT32_C_SUFFIX__ #else -# undef __int32_c_suffix -# endif /* __INT32_C_SUFFIX__ */ +#undef __int32_c_suffix +#endif /* __INT32_C_SUFFIX__ */ #endif /* __INT32_TYPE__ */ #ifdef __int_least32_t -# ifdef __int32_c_suffix -# define INT32_C(v) __int_c(v, __int32_c_suffix) -# define UINT32_C(v) __uint_c(v, __int32_c_suffix) -# else -# define INT32_C(v) v -# define UINT32_C(v) v ## U -# endif /* __int32_c_suffix */ +#ifdef __int32_c_suffix +#define INT32_C(v) __int_c(v, __int32_c_suffix) +#define UINT32_C(v) __uint_c(v, __int32_c_suffix) +#else +#define INT32_C(v) v +#define UINT32_C(v) v##U +#endif /* __int32_c_suffix */ #endif /* __int_least32_t */ #ifdef __INT16_TYPE__ -# ifdef __INT16_C_SUFFIX__ -# define __int16_c_suffix __INT16_C_SUFFIX__ +#ifdef __INT16_C_SUFFIX__ +#define __int16_c_suffix __INT16_C_SUFFIX__ #else -# undef __int16_c_suffix -# endif /* __INT16_C_SUFFIX__ */ +#undef __int16_c_suffix +#endif /* __INT16_C_SUFFIX__ */ #endif /* __INT16_TYPE__ */ #ifdef __int_least16_t -# ifdef __int16_c_suffix -# define INT16_C(v) __int_c(v, __int16_c_suffix) -# define UINT16_C(v) __uint_c(v, __int16_c_suffix) -# else -# define INT16_C(v) v -# define UINT16_C(v) v ## U -# endif /* __int16_c_suffix */ +#ifdef __int16_c_suffix +#define INT16_C(v) __int_c(v, __int16_c_suffix) +#define UINT16_C(v) __uint_c(v, __int16_c_suffix) +#else +#define INT16_C(v) v +#define UINT16_C(v) v##U +#endif /* __int16_c_suffix */ #endif /* __int_least16_t */ #ifdef __INT8_TYPE__ -# ifdef __INT8_C_SUFFIX__ -# define __int8_c_suffix __INT8_C_SUFFIX__ +#ifdef __INT8_C_SUFFIX__ +#define __int8_c_suffix __INT8_C_SUFFIX__ #else -# undef __int8_c_suffix -# endif /* __INT8_C_SUFFIX__ */ +#undef __int8_c_suffix +#endif /* __INT8_C_SUFFIX__ */ #endif /* __INT8_TYPE__ */ #ifdef __int_least8_t -# ifdef __int8_c_suffix -# define INT8_C(v) __int_c(v, __int8_c_suffix) -# define UINT8_C(v) __uint_c(v, __int8_c_suffix) -# else -# define INT8_C(v) v -# define UINT8_C(v) v ## U -# endif /* __int8_c_suffix */ +#ifdef __int8_c_suffix +#define INT8_C(v) __int_c(v, __int8_c_suffix) +#define UINT8_C(v) __uint_c(v, __int8_c_suffix) +#else +#define INT8_C(v) v +#define UINT8_C(v) v##U +#endif /* __int8_c_suffix */ #endif /* __int_least8_t */ /* C99 7.18.2.1 Limits of exact-width integer types. @@ -266,133 +274,131 @@ typedef __UINTMAX_TYPE__ uintmax_t; */ #ifdef __INT64_TYPE__ -# define INT64_MAX INT64_C( 9223372036854775807) -# define INT64_MIN (-INT64_C( 9223372036854775807)-1) -# define UINT64_MAX UINT64_C(18446744073709551615) -# define __INT_LEAST64_MIN INT64_MIN -# define __INT_LEAST64_MAX INT64_MAX -# define __UINT_LEAST64_MAX UINT64_MAX +#define INT64_MAX INT64_C(9223372036854775807) +#define INT64_MIN (-INT64_C(9223372036854775807) - 1) +#define UINT64_MAX UINT64_C(18446744073709551615) +#define __INT_LEAST64_MIN INT64_MIN +#define __INT_LEAST64_MAX INT64_MAX +#define __UINT_LEAST64_MAX UINT64_MAX #endif /* __INT64_TYPE__ */ #ifdef __INT_LEAST64_MIN -# define INT_LEAST64_MIN __INT_LEAST64_MIN -# define INT_LEAST64_MAX __INT_LEAST64_MAX -# define UINT_LEAST64_MAX __UINT_LEAST64_MAX -# define INT_FAST64_MIN __INT_LEAST64_MIN -# define INT_FAST64_MAX __INT_LEAST64_MAX -# define UINT_FAST64_MAX __UINT_LEAST64_MAX +#define INT_LEAST64_MIN __INT_LEAST64_MIN +#define INT_LEAST64_MAX __INT_LEAST64_MAX +#define UINT_LEAST64_MAX __UINT_LEAST64_MAX +#define INT_FAST64_MIN __INT_LEAST64_MIN +#define INT_FAST64_MAX __INT_LEAST64_MAX +#define UINT_FAST64_MAX __UINT_LEAST64_MAX #endif /* __INT_LEAST64_MIN */ #ifdef __INT32_TYPE__ -# define INT32_MAX INT32_C(2147483647) -# define INT32_MIN (-INT32_C(2147483647)-1) -# define UINT32_MAX UINT32_C(4294967295) -# define __INT_LEAST32_MIN INT32_MIN -# define __INT_LEAST32_MAX INT32_MAX -# define __UINT_LEAST32_MAX UINT32_MAX +#define INT32_MAX INT32_C(2147483647) +#define INT32_MIN (-INT32_C(2147483647) - 1) +#define UINT32_MAX UINT32_C(4294967295) +#define __INT_LEAST32_MIN INT32_MIN +#define __INT_LEAST32_MAX INT32_MAX +#define __UINT_LEAST32_MAX UINT32_MAX #endif /* __INT32_TYPE__ */ #ifdef __INT_LEAST32_MIN -# define INT_LEAST32_MIN __INT_LEAST32_MIN -# define INT_LEAST32_MAX __INT_LEAST32_MAX -# define UINT_LEAST32_MAX __UINT_LEAST32_MAX -# define INT_FAST32_MIN __INT_LEAST32_MIN -# define INT_FAST32_MAX __INT_LEAST32_MAX -# define UINT_FAST32_MAX __UINT_LEAST32_MAX +#define INT_LEAST32_MIN __INT_LEAST32_MIN +#define INT_LEAST32_MAX __INT_LEAST32_MAX +#define UINT_LEAST32_MAX __UINT_LEAST32_MAX +#define INT_FAST32_MIN __INT_LEAST32_MIN +#define INT_FAST32_MAX __INT_LEAST32_MAX +#define UINT_FAST32_MAX __UINT_LEAST32_MAX #endif /* __INT_LEAST32_MIN */ #ifdef __INT16_TYPE__ -#define INT16_MAX INT16_C(32767) -#define INT16_MIN (-INT16_C(32767)-1) -#define UINT16_MAX UINT16_C(65535) -# define __INT_LEAST16_MIN INT16_MIN -# define __INT_LEAST16_MAX INT16_MAX -# define __UINT_LEAST16_MAX UINT16_MAX +#define INT16_MAX INT16_C(32767) +#define INT16_MIN (-INT16_C(32767) - 1) +#define UINT16_MAX UINT16_C(65535) +#define __INT_LEAST16_MIN INT16_MIN +#define __INT_LEAST16_MAX INT16_MAX +#define __UINT_LEAST16_MAX UINT16_MAX #endif /* __INT16_TYPE__ */ #ifdef __INT_LEAST16_MIN -# define INT_LEAST16_MIN __INT_LEAST16_MIN -# define INT_LEAST16_MAX __INT_LEAST16_MAX -# define UINT_LEAST16_MAX __UINT_LEAST16_MAX -# define INT_FAST16_MIN __INT_LEAST16_MIN -# define INT_FAST16_MAX __INT_LEAST16_MAX -# define UINT_FAST16_MAX __UINT_LEAST16_MAX +#define INT_LEAST16_MIN __INT_LEAST16_MIN +#define INT_LEAST16_MAX __INT_LEAST16_MAX +#define UINT_LEAST16_MAX __UINT_LEAST16_MAX +#define INT_FAST16_MIN __INT_LEAST16_MIN +#define INT_FAST16_MAX __INT_LEAST16_MAX +#define UINT_FAST16_MAX __UINT_LEAST16_MAX #endif /* __INT_LEAST16_MIN */ #ifdef __INT8_TYPE__ -# define INT8_MAX INT8_C(127) -# define INT8_MIN (-INT8_C(127)-1) -# define UINT8_MAX UINT8_C(255) -# define __INT_LEAST8_MIN INT8_MIN -# define __INT_LEAST8_MAX INT8_MAX -# define __UINT_LEAST8_MAX UINT8_MAX +#define INT8_MAX INT8_C(127) +#define INT8_MIN (-INT8_C(127) - 1) +#define UINT8_MAX UINT8_C(255) +#define __INT_LEAST8_MIN INT8_MIN +#define __INT_LEAST8_MAX INT8_MAX +#define __UINT_LEAST8_MAX UINT8_MAX #endif /* __INT8_TYPE__ */ #ifdef __INT_LEAST8_MIN -# define INT_LEAST8_MIN __INT_LEAST8_MIN -# define INT_LEAST8_MAX __INT_LEAST8_MAX -# define UINT_LEAST8_MAX __UINT_LEAST8_MAX -# define INT_FAST8_MIN __INT_LEAST8_MIN -# define INT_FAST8_MAX __INT_LEAST8_MAX -# define UINT_FAST8_MAX __UINT_LEAST8_MAX +#define INT_LEAST8_MIN __INT_LEAST8_MIN +#define INT_LEAST8_MAX __INT_LEAST8_MAX +#define UINT_LEAST8_MAX __UINT_LEAST8_MAX +#define INT_FAST8_MIN __INT_LEAST8_MIN +#define INT_FAST8_MAX __INT_LEAST8_MAX +#define UINT_FAST8_MAX __UINT_LEAST8_MAX #endif /* __INT_LEAST8_MIN */ /* Some utility macros */ -#define __INTN_MIN(n) __stdint_join3( INT, n, _MIN) -#define __INTN_MAX(n) __stdint_join3( INT, n, _MAX) -#define __UINTN_MAX(n) __stdint_join3(UINT, n, _MAX) -#define __INTN_C(n, v) __stdint_join3( INT, n, _C(v)) +#define __INTN_MIN(n) __stdint_join3(INT, n, _MIN) +#define __INTN_MAX(n) __stdint_join3(INT, n, _MAX) +#define __UINTN_MAX(n) __stdint_join3(UINT, n, _MAX) +#define __INTN_C(n, v) __stdint_join3(INT, n, _C(v)) #define __UINTN_C(n, v) __stdint_join3(UINT, n, _C(v)) /* C99 7.18.2.4 Limits of integer types capable of holding object pointers. */ /* C99 7.18.3 Limits of other integer types. */ -#define INTPTR_MIN (-__INTPTR_MAX__-1) -#define INTPTR_MAX __INTPTR_MAX__ -#define UINTPTR_MAX __UINTPTR_MAX__ -#define PTRDIFF_MIN (-__PTRDIFF_MAX__-1) -#define PTRDIFF_MAX __PTRDIFF_MAX__ -#define SIZE_MAX __SIZE_MAX__ +#define INTPTR_MIN (-__INTPTR_MAX__ - 1) +#define INTPTR_MAX __INTPTR_MAX__ +#define UINTPTR_MAX __UINTPTR_MAX__ +#define PTRDIFF_MIN (-__PTRDIFF_MAX__ - 1) +#define PTRDIFF_MAX __PTRDIFF_MAX__ +#define SIZE_MAX __SIZE_MAX__ /* ISO9899:2011 7.20 (C11 Annex K): Define RSIZE_MAX if __STDC_WANT_LIB_EXT1__ * is enabled. */ #if defined(__STDC_WANT_LIB_EXT1__) && __STDC_WANT_LIB_EXT1__ >= 1 -#define RSIZE_MAX (SIZE_MAX >> 1) +#define RSIZE_MAX (SIZE_MAX >> 1) #endif /* C99 7.18.2.5 Limits of greatest-width integer types. */ -#define INTMAX_MIN (-__INTMAX_MAX__-1) -#define INTMAX_MAX __INTMAX_MAX__ -#define UINTMAX_MAX __UINTMAX_MAX__ +#define INTMAX_MIN (-__INTMAX_MAX__ - 1) +#define INTMAX_MAX __INTMAX_MAX__ +#define UINTMAX_MAX __UINTMAX_MAX__ /* C99 7.18.3 Limits of other integer types. */ #define SIG_ATOMIC_MIN __INTN_MIN(__SIG_ATOMIC_WIDTH__) #define SIG_ATOMIC_MAX __INTN_MAX(__SIG_ATOMIC_WIDTH__) #ifdef __WINT_UNSIGNED__ -# define WINT_MIN __UINTN_C(__WINT_WIDTH__, 0) -# define WINT_MAX __UINTN_MAX(__WINT_WIDTH__) +#define WINT_MIN __UINTN_C(__WINT_WIDTH__, 0) +#define WINT_MAX __UINTN_MAX(__WINT_WIDTH__) #else -# define WINT_MIN __INTN_MIN(__WINT_WIDTH__) -# define WINT_MAX __INTN_MAX(__WINT_WIDTH__) +#define WINT_MIN __INTN_MIN(__WINT_WIDTH__) +#define WINT_MAX __INTN_MAX(__WINT_WIDTH__) #endif #ifndef WCHAR_MAX -# define WCHAR_MAX __WCHAR_MAX__ +#define WCHAR_MAX __WCHAR_MAX__ #endif #ifndef WCHAR_MIN -# if __WCHAR_MAX__ == __INTN_MAX(__WCHAR_WIDTH__) -# define WCHAR_MIN __INTN_MIN(__WCHAR_WIDTH__) -# else -# define WCHAR_MIN __UINTN_C(__WCHAR_WIDTH__, 0) -# endif +#if __WCHAR_MAX__ == __INTN_MAX(__WCHAR_WIDTH__) +#define WCHAR_MIN __INTN_MIN(__WCHAR_WIDTH__) +#else +#define WCHAR_MIN __UINTN_C(__WCHAR_WIDTH__, 0) +#endif #endif /* 7.18.4.2 Macros for greatest-width integer constants. */ -#define INTMAX_C(v) __int_c(v, __INTMAX_C_SUFFIX__) +#define INTMAX_C(v) __int_c(v, __INTMAX_C_SUFFIX__) #define UINTMAX_C(v) __int_c(v, __UINTMAX_C_SUFFIX__) #endif // SLANG_LLVM_H - - diff --git a/prelude/slang-torch-prelude.h b/prelude/slang-torch-prelude.h index 11ffe3b66..d303c1045 100644 --- a/prelude/slang-torch-prelude.h +++ b/prelude/slang-torch-prelude.h @@ -1,64 +1,67 @@ // Prelude for PyTorch cpp binding. -#include #include #include -#include #include #include +#include +#include #ifdef SLANG_LLVM #include "slang-llvm.h" #else // SLANG_LLVM -# if SLANG_GCC_FAMILY && __GNUC__ < 6 -# include -# define SLANG_PRELUDE_STD std:: -# else -# include -# define SLANG_PRELUDE_STD -# endif - -# include -# include -# include -# include +#if SLANG_GCC_FAMILY && __GNUC__ < 6 +#include +#define SLANG_PRELUDE_STD std:: +#else +#include +#define SLANG_PRELUDE_STD +#endif + +#include +#include +#include +#include #endif // SLANG_LLVM #include "../source/core/slang-string.h" #if defined(_MSC_VER) -# define SLANG_PRELUDE_SHARED_LIB_EXPORT __declspec(dllexport) +#define SLANG_PRELUDE_SHARED_LIB_EXPORT __declspec(dllexport) #else -# define SLANG_PRELUDE_SHARED_LIB_EXPORT __attribute__((__visibility__("default"))) -//# define SLANG_PRELUDE_SHARED_LIB_EXPORT __attribute__ ((dllexport)) __attribute__((__visibility__("default"))) -#endif - -#ifdef __cplusplus -# define SLANG_PRELUDE_EXTERN_C extern "C" -# define SLANG_PRELUDE_EXTERN_C_START extern "C" { -# define SLANG_PRELUDE_EXTERN_C_END } +#define SLANG_PRELUDE_SHARED_LIB_EXPORT __attribute__((__visibility__("default"))) +// # define SLANG_PRELUDE_SHARED_LIB_EXPORT __attribute__ ((dllexport)) +// __attribute__((__visibility__("default"))) +#endif + +#ifdef __cplusplus +#define SLANG_PRELUDE_EXTERN_C extern "C" +#define SLANG_PRELUDE_EXTERN_C_START \ + extern "C" \ + { +#define SLANG_PRELUDE_EXTERN_C_END } #else -# define SLANG_PRELUDE_EXTERN_C -# define SLANG_PRELUDE_EXTERN_C_START -# define SLANG_PRELUDE_EXTERN_C_END -#endif +#define SLANG_PRELUDE_EXTERN_C +#define SLANG_PRELUDE_EXTERN_C_START +#define SLANG_PRELUDE_EXTERN_C_END +#endif #define SLANG_PRELUDE_NAMESPACE #ifndef SLANG_NO_THROW -# define SLANG_NO_THROW +#define SLANG_NO_THROW #endif #ifndef SLANG_STDCALL -# define SLANG_STDCALL +#define SLANG_STDCALL #endif #ifndef SLANG_MCALL -# define SLANG_MCALL SLANG_STDCALL +#define SLANG_MCALL SLANG_STDCALL #endif #ifndef SLANG_FORCE_INLINE -# define SLANG_FORCE_INLINE inline +#define SLANG_FORCE_INLINE inline #endif -#include "slang-cpp-types-core.h" #include "slang-cpp-scalar-intrinsics.h" +#include "slang-cpp-types-core.h" static const int kSlangTorchTensorMaxDim = 5; @@ -72,20 +75,26 @@ struct TensorView }; -TensorView make_tensor_view(torch::Tensor val, const char* name, torch::ScalarType targetScalarType, bool requireContiguous) +TensorView make_tensor_view( + torch::Tensor val, + const char* name, + torch::ScalarType targetScalarType, + bool requireContiguous) { // We're currently not trying to implicitly cast or transfer to device for two reasons: // 1. There appears to be a bug with .to() where successive calls after the first one fail. - // 2. Silent casts like this can cause large memory allocations & unexpected overheads. + // 2. Silent casts like this can cause large memory allocations & unexpected overheads. // It's better to be explicit. // Expect tensors to be on CUDA device if (!val.device().is_cuda()) - throw std::runtime_error(std::string(name).append(": tensor is not on CUDA device.").c_str()); + throw std::runtime_error( + std::string(name).append(": tensor is not on CUDA device.").c_str()); // Expect tensors to be the right type. if (val.dtype() != targetScalarType) - throw std::runtime_error(std::string(name).append(": tensor is not of the expected type.").c_str()); + throw std::runtime_error( + std::string(name).append(": tensor is not of the expected type.").c_str()); // Check that the tensor is contiguous if (requireContiguous && !val.is_contiguous()) @@ -138,14 +147,22 @@ TensorView make_tensor_view(torch::Tensor val, const char* name, torch::ScalarTy } if (val.dim() > kSlangTorchTensorMaxDim) - throw std::runtime_error(std::string(name).append(": number of dimensions exceeds limit (").append(std::to_string(kSlangTorchTensorMaxDim)).append(")").c_str()); + throw std::runtime_error(std::string(name) + .append(": number of dimensions exceeds limit (") + .append(std::to_string(kSlangTorchTensorMaxDim)) + .append(")") + .c_str()); bool isEmpty = true; for (int i = 0; i < val.dim(); ++i) { res.strides[i] = val.stride(i) * elementSize; if (res.strides[i] == 0) - throw std::runtime_error(std::string(name).append(": tensors with broadcasted dimensions are not supported (use tensor.contiguous() to make tensor whole)").c_str()); + throw std::runtime_error( + std::string(name) + .append(": tensors with broadcasted dimensions are not supported (use " + "tensor.contiguous() to make tensor whole)") + .c_str()); res.sizes[i] = val.size(i); if (res.sizes[i] > 0) diff --git a/source/compiler-core/slang-artifact-associated-impl.cpp b/source/compiler-core/slang-artifact-associated-impl.cpp index 07d69bf8e..cbecd1360 100644 --- a/source/compiler-core/slang-artifact-associated-impl.cpp +++ b/source/compiler-core/slang-artifact-associated-impl.cpp @@ -1,30 +1,28 @@ // slang-artifact-associated-impl.cpp #include "slang-artifact-associated-impl.h" -#include "../core/slang-file-system.h" - -#include "../core/slang-type-text-util.h" -#include "../core/slang-io.h" #include "../core/slang-array-view.h" - #include "../core/slang-char-util.h" - +#include "../core/slang-file-system.h" +#include "../core/slang-io.h" +#include "../core/slang-type-text-util.h" #include "slang-artifact-diagnostic-util.h" -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactDiagnostics !!!!!!!!!!!!!!!!!!!!!!!!!!! */ -ArtifactDiagnostics::ArtifactDiagnostics(const ThisType& rhs): - ComBaseObject(), - m_result(rhs.m_result), - m_diagnostics(rhs.m_diagnostics), - m_raw(rhs.m_raw.getLength() + 1) +ArtifactDiagnostics::ArtifactDiagnostics(const ThisType& rhs) + : ComBaseObject() + , m_result(rhs.m_result) + , m_diagnostics(rhs.m_diagnostics) + , m_raw(rhs.m_raw.getLength() + 1) { // We need to be careful with raw, we want a new *copy* not a non atomic ref counting // In initialization we should have enough space m_raw.append(rhs.m_raw.getUnownedSlice()); - + // Reallocate all the strings for (auto& diagnostic : m_diagnostics) { @@ -41,17 +39,15 @@ void* ArtifactDiagnostics::clone(const Guid& guid) { return ptr; } - // If the cast fails, we delete the item. + // If the cast fails, we delete the item. delete copy; return nullptr; } void* ArtifactDiagnostics::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || - guid == IClonable::getTypeGuid() || - guid == IArtifactDiagnostics::getTypeGuid()) + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || + guid == IClonable::getTypeGuid() || guid == IArtifactDiagnostics::getTypeGuid()) { return static_cast(this); } @@ -108,7 +104,7 @@ void ArtifactDiagnostics::appendRaw(const CharSlice& slice) m_raw << asStringSlice(slice); } -Count ArtifactDiagnostics::getCountAtLeastSeverity(Diagnostic::Severity severity) +Count ArtifactDiagnostics::getCountAtLeastSeverity(Diagnostic::Severity severity) { Index count = 0; for (const auto& msg : m_diagnostics) @@ -140,7 +136,9 @@ bool ArtifactDiagnostics::hasOfAtLeastSeverity(Diagnostic::Severity severity) return false; } -Count ArtifactDiagnostics::getCountByStage(Diagnostic::Stage stage, Count outCounts[Int(Diagnostic::Severity::CountOf)]) +Count ArtifactDiagnostics::getCountByStage( + Diagnostic::Stage stage, + Count outCounts[Int(Diagnostic::Severity::CountOf)]) { Int count = 0; ::memset(outCounts, 0, sizeof(Index) * Int(Diagnostic::Severity::CountOf)); @@ -174,7 +172,7 @@ void ArtifactDiagnostics::maybeAddNote(const CharSlice& in) ArtifactDiagnosticUtil::maybeAddNote(asStringSlice(in), this); } -void ArtifactDiagnostics::requireErrorDiagnostic() +void ArtifactDiagnostics::requireErrorDiagnostic() { // If we find an error, we don't need to add a generic diagnostic for (const auto& msg : m_diagnostics) @@ -193,19 +191,21 @@ void ArtifactDiagnostics::requireErrorDiagnostic() m_diagnostics.add(diagnostic); } -/* static */UnownedStringSlice _getSeverityText(ArtifactDiagnostic::Severity severity) +/* static */ UnownedStringSlice _getSeverityText(ArtifactDiagnostic::Severity severity) { typedef ArtifactDiagnostic::Severity Severity; switch (severity) { - default: return UnownedStringSlice::fromLiteral("Unknown"); - case Severity::Info: return UnownedStringSlice::fromLiteral("Info"); - case Severity::Warning: return UnownedStringSlice::fromLiteral("Warning"); - case Severity::Error: return UnownedStringSlice::fromLiteral("Error"); + default: return UnownedStringSlice::fromLiteral("Unknown"); + case Severity::Info: return UnownedStringSlice::fromLiteral("Info"); + case Severity::Warning: return UnownedStringSlice::fromLiteral("Warning"); + case Severity::Error: return UnownedStringSlice::fromLiteral("Error"); } } -static void _appendCounts(const Index counts[Int(ArtifactDiagnostic::Severity::CountOf)], StringBuilder& out) +static void _appendCounts( + const Index counts[Int(ArtifactDiagnostic::Severity::CountOf)], + StringBuilder& out) { typedef ArtifactDiagnostic::Severity Severity; @@ -218,7 +218,9 @@ static void _appendCounts(const Index counts[Int(ArtifactDiagnostic::Severity::C } } -static void _appendSimplified(const Index counts[Int(ArtifactDiagnostic::Severity::CountOf)], StringBuilder& out) +static void _appendSimplified( + const Index counts[Int(ArtifactDiagnostic::Severity::CountOf)], + StringBuilder& out) { typedef ArtifactDiagnostic::Severity Severity; for (Index i = 0; i < Int(Severity::CountOf); i++) @@ -276,8 +278,7 @@ void ArtifactDiagnostics::calcSimplifiedSummary(ISlangBlob** outBlob) void* ArtifactPostEmitMetadata::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IArtifactPostEmitMetadata::getTypeGuid()) { return static_cast(this); @@ -304,13 +305,15 @@ void* ArtifactPostEmitMetadata::castAs(const Guid& guid) } Slice ArtifactPostEmitMetadata::getUsedBindingRanges() -{ - return Slice(m_usedBindings.getBuffer(), m_usedBindings.getCount()); +{ + return Slice(m_usedBindings.getBuffer(), m_usedBindings.getCount()); } Slice ArtifactPostEmitMetadata::getExportedFunctionMangledNames() { - return Slice(m_exportedFunctionMangledNames.getBuffer(), m_exportedFunctionMangledNames.getCount()); + return Slice( + m_exportedFunctionMangledNames.getBuffer(), + m_exportedFunctionMangledNames.getCount()); } SlangResult ArtifactPostEmitMetadata::isParameterLocationUsed( diff --git a/source/compiler-core/slang-artifact-associated-impl.h b/source/compiler-core/slang-artifact-associated-impl.h index d11498604..515cedb2d 100644 --- a/source/compiler-core/slang-artifact-associated-impl.h +++ b/source/compiler-core/slang-artifact-associated-impl.h @@ -2,17 +2,13 @@ #ifndef SLANG_ARTIFACT_ASSOCIATED_IMPL_H #define SLANG_ARTIFACT_ASSOCIATED_IMPL_H -#include "slang-com-helper.h" -#include "slang-com-ptr.h" - #include "../core/slang-com-object.h" #include "../core/slang-memory-arena.h" - #include "slang-artifact-associated.h" - -#include "slang-artifact-util.h" - #include "slang-artifact-diagnostic-util.h" +#include "slang-artifact-util.h" +#include "slang-com-helper.h" +#include "slang-com-ptr.h" namespace Slang { @@ -29,33 +25,61 @@ public: // IClonable SLANG_NO_THROW virtual void* SLANG_MCALL clone(const Guid& intf) SLANG_OVERRIDE; // IDiagnostic - SLANG_NO_THROW virtual const Diagnostic* SLANG_MCALL getAt(Index i) SLANG_OVERRIDE { return &m_diagnostics[i]; } - SLANG_NO_THROW virtual Count SLANG_MCALL getCount() SLANG_OVERRIDE { return m_diagnostics.getCount(); } - SLANG_NO_THROW virtual void SLANG_MCALL add(const Diagnostic& diagnostic) SLANG_OVERRIDE; - SLANG_NO_THROW virtual void SLANG_MCALL removeAt(Index i) SLANG_OVERRIDE { m_diagnostics.removeAt(i); } + SLANG_NO_THROW virtual const Diagnostic* SLANG_MCALL getAt(Index i) SLANG_OVERRIDE + { + return &m_diagnostics[i]; + } + SLANG_NO_THROW virtual Count SLANG_MCALL getCount() SLANG_OVERRIDE + { + return m_diagnostics.getCount(); + } + SLANG_NO_THROW virtual void SLANG_MCALL add(const Diagnostic& diagnostic) SLANG_OVERRIDE; + SLANG_NO_THROW virtual void SLANG_MCALL removeAt(Index i) SLANG_OVERRIDE + { + m_diagnostics.removeAt(i); + } SLANG_NO_THROW virtual SlangResult SLANG_MCALL getResult() SLANG_OVERRIDE { return m_result; } - SLANG_NO_THROW virtual void SLANG_MCALL setResult(SlangResult res) SLANG_OVERRIDE { m_result = res; } + SLANG_NO_THROW virtual void SLANG_MCALL setResult(SlangResult res) SLANG_OVERRIDE + { + m_result = res; + } SLANG_NO_THROW virtual void SLANG_MCALL setRaw(const CharSlice& slice) SLANG_OVERRIDE; SLANG_NO_THROW virtual void SLANG_MCALL appendRaw(const CharSlice& slice) SLANG_OVERRIDE; - SLANG_NO_THROW virtual TerminatedCharSlice SLANG_MCALL getRaw() SLANG_OVERRIDE { return SliceUtil::asTerminatedCharSlice(m_raw); } + SLANG_NO_THROW virtual TerminatedCharSlice SLANG_MCALL getRaw() SLANG_OVERRIDE + { + return SliceUtil::asTerminatedCharSlice(m_raw); + } SLANG_NO_THROW virtual void SLANG_MCALL reset() SLANG_OVERRIDE; - SLANG_NO_THROW virtual Count SLANG_MCALL getCountAtLeastSeverity(Diagnostic::Severity severity) SLANG_OVERRIDE; - SLANG_NO_THROW virtual Count SLANG_MCALL getCountBySeverity(Diagnostic::Severity severity) SLANG_OVERRIDE; - SLANG_NO_THROW virtual bool SLANG_MCALL hasOfAtLeastSeverity(Diagnostic::Severity severity) SLANG_OVERRIDE; - SLANG_NO_THROW virtual Count SLANG_MCALL getCountByStage(Diagnostic::Stage stage, Count outCounts[Int(Diagnostic::Severity::CountOf)]) SLANG_OVERRIDE; - SLANG_NO_THROW virtual void SLANG_MCALL removeBySeverity(Diagnostic::Severity severity) SLANG_OVERRIDE; + SLANG_NO_THROW virtual Count SLANG_MCALL getCountAtLeastSeverity(Diagnostic::Severity severity) + SLANG_OVERRIDE; + SLANG_NO_THROW virtual Count SLANG_MCALL getCountBySeverity(Diagnostic::Severity severity) + SLANG_OVERRIDE; + SLANG_NO_THROW virtual bool SLANG_MCALL hasOfAtLeastSeverity(Diagnostic::Severity severity) + SLANG_OVERRIDE; + SLANG_NO_THROW virtual Count SLANG_MCALL getCountByStage( + Diagnostic::Stage stage, + Count outCounts[Int(Diagnostic::Severity::CountOf)]) SLANG_OVERRIDE; + SLANG_NO_THROW virtual void SLANG_MCALL removeBySeverity(Diagnostic::Severity severity) + SLANG_OVERRIDE; SLANG_NO_THROW virtual void SLANG_MCALL maybeAddNote(const CharSlice& in) SLANG_OVERRIDE; SLANG_NO_THROW virtual void SLANG_MCALL requireErrorDiagnostic() SLANG_OVERRIDE; SLANG_NO_THROW virtual void SLANG_MCALL calcSummary(ISlangBlob** outBlob) SLANG_OVERRIDE; - SLANG_NO_THROW virtual void SLANG_MCALL calcSimplifiedSummary(ISlangBlob** outBlob) SLANG_OVERRIDE; + SLANG_NO_THROW virtual void SLANG_MCALL calcSimplifiedSummary(ISlangBlob** outBlob) + SLANG_OVERRIDE; - /// Default ctor - ArtifactDiagnostics():ComBaseObject() {} - /// Copy ctor + /// Default ctor + ArtifactDiagnostics() + : ComBaseObject() + { + } + /// Copy ctor ArtifactDiagnostics(const ThisType& rhs); - /// Create - static ComPtr create() { return ComPtr(new ThisType); } + /// Create + static ComPtr create() + { + return ComPtr(new ThisType); + } protected: void* getInterface(const Guid& uuid); @@ -65,7 +89,7 @@ protected: List m_diagnostics; SlangResult m_result = SLANG_OK; - + // Raw diagnostics StringBuilder m_raw; }; @@ -79,17 +103,14 @@ struct ShaderBindingRange UInt registerIndex = 0; UInt registerCount = 0; // 0 for unsized - bool isInfinite() const - { - return registerCount == 0; - } + bool isInfinite() const { return registerCount == 0; } - bool containsBinding(slang::ParameterCategory _category, UInt _spaceIndex, UInt _registerIndex) const + bool containsBinding(slang::ParameterCategory _category, UInt _spaceIndex, UInt _registerIndex) + const { - return category == _category - && spaceIndex == _spaceIndex - && registerIndex <= _registerIndex - && (isInfinite() || registerCount + registerIndex > _registerIndex); + return category == _category && spaceIndex == _spaceIndex && + registerIndex <= _registerIndex && + (isInfinite() || registerCount + registerIndex > _registerIndex); } bool intersectsWith(const ShaderBindingRange& other) const @@ -97,8 +118,10 @@ struct ShaderBindingRange if (category != other.category || spaceIndex != other.spaceIndex) return false; - const bool leftIntersection = (registerIndex < other.registerIndex + other.registerCount) || other.isInfinite(); - const bool rightIntersection = (other.registerIndex < registerIndex + registerCount) || isInfinite(); + const bool leftIntersection = + (registerIndex < other.registerIndex + other.registerCount) || other.isInfinite(); + const bool rightIntersection = + (other.registerIndex < registerIndex + registerCount) || isInfinite(); return leftIntersection && rightIntersection; } @@ -108,8 +131,10 @@ struct ShaderBindingRange if (category != other.category || spaceIndex != other.spaceIndex) return false; - const bool leftIntersection = (registerIndex <= other.registerIndex + other.registerCount) || other.isInfinite(); - const bool rightIntersection = (other.registerIndex <= registerIndex + registerCount) || isInfinite(); + const bool leftIntersection = + (registerIndex <= other.registerIndex + other.registerCount) || other.isInfinite(); + const bool rightIntersection = + (other.registerIndex <= registerIndex + registerCount) || isInfinite(); return leftIntersection && rightIntersection; } @@ -121,7 +146,10 @@ struct ShaderBindingRange if (other.isInfinite()) registerCount = 0; else if (!isInfinite()) - registerCount = Math::Max(registerIndex + registerCount, other.registerIndex + other.registerCount) - newRegisterIndex; + registerCount = Math::Max( + registerIndex + registerCount, + other.registerIndex + other.registerCount) - + newRegisterIndex; registerIndex = newRegisterIndex; } @@ -134,10 +162,8 @@ struct ShaderBindingRange case slang::ShaderResource: case slang::UnorderedAccess: case slang::SamplerState: - case slang::DescriptorTableSlot: - return true; - default: - return false; + case slang::DescriptorTableSlot: return true; + default: return false; } } }; @@ -147,28 +173,33 @@ class ArtifactPostEmitMetadata : public ComBaseObject, public IArtifactPostEmitM public: typedef ArtifactPostEmitMetadata ThisType; - SLANG_CLASS_GUID(0x6f82509f, 0xe48b, 0x4b83, { 0xa3, 0x84, 0x5d, 0x70, 0x83, 0x19, 0x83, 0xcc }) + SLANG_CLASS_GUID(0x6f82509f, 0xe48b, 0x4b83, {0xa3, 0x84, 0x5d, 0x70, 0x83, 0x19, 0x83, 0xcc}) SLANG_COM_BASE_IUNKNOWN_ALL // ICastable SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; - + // IArtifactPostEmitMetadata - SLANG_NO_THROW virtual Slice SLANG_MCALL getUsedBindingRanges() SLANG_OVERRIDE; - SLANG_NO_THROW virtual Slice SLANG_MCALL getExportedFunctionMangledNames() SLANG_OVERRIDE; + SLANG_NO_THROW virtual Slice SLANG_MCALL getUsedBindingRanges() + SLANG_OVERRIDE; + SLANG_NO_THROW virtual Slice SLANG_MCALL getExportedFunctionMangledNames() + SLANG_OVERRIDE; // IMetadata SLANG_NO_THROW virtual SlangResult SLANG_MCALL isParameterLocationUsed( SlangParameterCategory category, // is this a `t` register? `s` register? - SlangUInt spaceIndex, // `space` for D3D12, `set` for Vulkan - SlangUInt registerIndex, // `register` for D3D12, `binding` for Vulkan + SlangUInt spaceIndex, // `space` for D3D12, `set` for Vulkan + SlangUInt registerIndex, // `register` for D3D12, `binding` for Vulkan bool& outUsed) SLANG_OVERRIDE; void* getInterface(const Guid& uuid); void* getObject(const Guid& uuid); - static ComPtr create() { return ComPtr(new ThisType); } + static ComPtr create() + { + return ComPtr(new ThisType); + } List m_usedBindings; List m_exportedFunctionMangledNames; diff --git a/source/compiler-core/slang-artifact-associated.h b/source/compiler-core/slang-artifact-associated.h index 91ae09aab..c8e74f98b 100644 --- a/source/compiler-core/slang-artifact-associated.h +++ b/source/compiler-core/slang-artifact-associated.h @@ -28,29 +28,29 @@ struct ArtifactDiagnostic struct Location { typedef Location ThisType; - bool operator==(const ThisType& rhs) const { return line == rhs.line && column == rhs.column; } + bool operator==(const ThisType& rhs) const + { + return line == rhs.line && column == rhs.column; + } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - Int line = 0; ///< One indexed line number. 0 if not defined - Int column = 0; ///< One indexed *character (not byte)* column number. 0 if not defined + Int line = 0; ///< One indexed line number. 0 if not defined + Int column = 0; ///< One indexed *character (not byte)* column number. 0 if not defined }; bool operator==(const ThisType& rhs) const { - return severity == rhs.severity && - stage == rhs.stage && - text == rhs.text && - code == rhs.code && - location == rhs.location; + return severity == rhs.severity && stage == rhs.stage && text == rhs.text && + code == rhs.code && location == rhs.location; } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - Severity severity = Severity::Unknown; ///< The severity of error - Stage stage = Stage::Compile; ///< The stage the error came from - TerminatedCharSlice text; ///< The text of the error - TerminatedCharSlice code; ///< The compiler specific error code - TerminatedCharSlice filePath; ///< The path the error originated from - Location location; ///< The location of the diagnostic in the filePath + Severity severity = Severity::Unknown; ///< The severity of error + Stage stage = Stage::Compile; ///< The stage the error came from + TerminatedCharSlice text; ///< The text of the error + TerminatedCharSlice code; ///< The compiler specific error code + TerminatedCharSlice filePath; ///< The path the error originated from + Location location; ///< The location of the diagnostic in the filePath }; /* Artifact diagnostics interface. @@ -60,58 +60,65 @@ IArtifactDiagnostics are added as associated types on an IArtifact typically. class IArtifactDiagnostics : public IClonable { public: - SLANG_COM_INTERFACE(0x91f9b857, 0xcd6b, 0x45ca, { 0x8e, 0x3, 0x8f, 0xa3, 0x3c, 0x5c, 0xf0, 0x1a }); + SLANG_COM_INTERFACE( + 0x91f9b857, + 0xcd6b, + 0x45ca, + {0x8e, 0x3, 0x8f, 0xa3, 0x3c, 0x5c, 0xf0, 0x1a}); typedef ArtifactDiagnostic Diagnostic; - /// Get the diagnostic at the index + /// Get the diagnostic at the index SLANG_NO_THROW virtual const Diagnostic* SLANG_MCALL getAt(Index i) = 0; - /// Get the amount of diangostics + /// Get the amount of diangostics SLANG_NO_THROW virtual Count SLANG_MCALL getCount() = 0; - /// Add a diagnostic + /// Add a diagnostic SLANG_NO_THROW virtual void SLANG_MCALL add(const Diagnostic& diagnostic) = 0; - /// Remove the diagnostic at the index + /// Remove the diagnostic at the index SLANG_NO_THROW virtual void SLANG_MCALL removeAt(Index i) = 0; - /// Get raw diagnostics information + /// Get raw diagnostics information SLANG_NO_THROW virtual TerminatedCharSlice SLANG_MCALL getRaw() = 0; - /// Set the raw diagnostic info + /// Set the raw diagnostic info SLANG_NO_THROW virtual void SLANG_MCALL setRaw(const CharSlice& slice) = 0; - /// Append to the raw diagnostic + /// Append to the raw diagnostic SLANG_NO_THROW virtual void SLANG_MCALL appendRaw(const CharSlice& slice) = 0; - /// Get the result for a compilation + /// Get the result for a compilation SLANG_NO_THROW virtual SlangResult SLANG_MCALL getResult() = 0; - /// Set the result + /// Set the result SLANG_NO_THROW virtual void SLANG_MCALL setResult(SlangResult res) = 0; - /// Reset all state + /// Reset all state SLANG_NO_THROW virtual void SLANG_MCALL reset() = 0; - /// Count the number of diagnostics which have 'severity' or greater - SLANG_NO_THROW virtual Count SLANG_MCALL getCountAtLeastSeverity(Diagnostic::Severity severity) = 0; + /// Count the number of diagnostics which have 'severity' or greater + SLANG_NO_THROW virtual Count SLANG_MCALL + getCountAtLeastSeverity(Diagnostic::Severity severity) = 0; - /// Get the number of diagnostics by severity + /// Get the number of diagnostics by severity SLANG_NO_THROW virtual Count SLANG_MCALL getCountBySeverity(Diagnostic::Severity severity) = 0; - /// True if there are any diagnostics of severity or worse + /// True if there are any diagnostics of severity or worse SLANG_NO_THROW virtual bool SLANG_MCALL hasOfAtLeastSeverity(Diagnostic::Severity severity) = 0; - /// Stores in outCounts, the amount of diagnostics for the stage of each severity - SLANG_NO_THROW virtual Count SLANG_MCALL getCountByStage(Diagnostic::Stage stage, Count outCounts[Int(Diagnostic::Severity::CountOf)]) = 0; + /// Stores in outCounts, the amount of diagnostics for the stage of each severity + SLANG_NO_THROW virtual Count SLANG_MCALL getCountByStage( + Diagnostic::Stage stage, + Count outCounts[Int(Diagnostic::Severity::CountOf)]) = 0; - /// Remove all diagnostics of the type + /// Remove all diagnostics of the type SLANG_NO_THROW virtual void SLANG_MCALL removeBySeverity(Diagnostic::Severity severity) = 0; - /// Add a note + /// Add a note SLANG_NO_THROW virtual void SLANG_MCALL maybeAddNote(const CharSlice& in) = 0; - /// If there are no error diagnostics, adds a generic error diagnostic + /// If there are no error diagnostics, adds a generic error diagnostic SLANG_NO_THROW virtual void SLANG_MCALL requireErrorDiagnostic() = 0; - /// Creates summary text and place in outBlob + /// Creates summary text and place in outBlob SLANG_NO_THROW virtual void SLANG_MCALL calcSummary(ISlangBlob** outBlob) = 0; - /// Creates a simplified summary text and places it in out blob + /// Creates a simplified summary text and places it in out blob SLANG_NO_THROW virtual void SLANG_MCALL calcSimplifiedSummary(ISlangBlob** outBlob) = 0; }; @@ -120,12 +127,16 @@ struct ShaderBindingRange; class IArtifactPostEmitMetadata : public slang::IMetadata { public: - SLANG_COM_INTERFACE(0x5d03bce9, 0xafb1, 0x4fc8, { 0xa4, 0x6f, 0x3c, 0xe0, 0x7b, 0x6, 0x1b, 0x1b }); + SLANG_COM_INTERFACE( + 0x5d03bce9, + 0xafb1, + 0x4fc8, + {0xa4, 0x6f, 0x3c, 0xe0, 0x7b, 0x6, 0x1b, 0x1b}); - /// Get the binding ranges + /// Get the binding ranges SLANG_NO_THROW virtual Slice SLANG_MCALL getUsedBindingRanges() = 0; - /// Get the list of functions that were exported in the linked IR + /// Get the list of functions that were exported in the linked IR SLANG_NO_THROW virtual Slice SLANG_MCALL getExportedFunctionMangledNames() = 0; }; diff --git a/source/compiler-core/slang-artifact-container-util.cpp b/source/compiler-core/slang-artifact-container-util.cpp index 1c9bb5a69..935cabe8f 100644 --- a/source/compiler-core/slang-artifact-container-util.cpp +++ b/source/compiler-core/slang-artifact-container-util.cpp @@ -1,27 +1,27 @@ // slang-artifact-container-util.cpp #include "slang-artifact-container-util.h" -#include "slang-artifact-util.h" -#include "slang-artifact-desc-util.h" -#include "slang-artifact-representation-impl.h" - +#include "../core/slang-castable.h" #include "../core/slang-file-system.h" #include "../core/slang-io.h" -#include "../core/slang-zip-file-system.h" -#include "../core/slang-castable.h" #include "../core/slang-string-slice-pool.h" +#include "../core/slang-zip-file-system.h" +#include "slang-artifact-desc-util.h" +#include "slang-artifact-representation-impl.h" +#include "slang-artifact-util.h" -namespace Slang { +namespace Slang +{ -/* +/* Artifact file structure ======================= -There is many ways this could work, with different trade offs. The approach taken here is -to make *every* artifact be a directory. There are two special case directories "associated" and "children", -which hold the artifacts associated/chidren artifacts. +There is many ways this could work, with different trade offs. The approach taken here is +to make *every* artifact be a directory. There are two special case directories "associated" and +"children", which hold the artifacts associated/chidren artifacts. -So for example if we have +So for example if we have ``` thing.spv @@ -53,11 +53,12 @@ associated/0a0a0a/0a0a0a.map associated/0b0b0b/0b0b0b.map ``` -That is a little verbose, but if the associated artifacts have children/associated, then things still work. +That is a little verbose, but if the associated artifacts have children/associated, then things +still work. ``` container - a.spv + a.spv associated diagnostics b.dxil @@ -127,7 +128,7 @@ struct ArtifactContainerWriter { push(name); - const char*const path = m_entry.path.getBuffer(); + const char* const path = m_entry.path.getBuffer(); SlangPathType pathType; if (SLANG_SUCCEEDED(m_fileSystem->getPathType(path, &pathType))) @@ -137,7 +138,7 @@ struct ArtifactContainerWriter return SLANG_FAIL; } } - + // Make sure there is a path to this return m_fileSystem->createDirectory(m_entry.path.getBuffer()); } @@ -150,12 +151,12 @@ struct ArtifactContainerWriter SlangResult getBaseName(IArtifact* artifact, String& out); - /// Write the artifact in the current scope + /// Write the artifact in the current scope SlangResult write(IArtifact* artifact); SlangResult writeInDirectory(IArtifact* artifact, const String& baseName); - ArtifactContainerWriter(ISlangMutableFileSystem* fileSystem): - m_fileSystem(fileSystem) + ArtifactContainerWriter(ISlangMutableFileSystem* fileSystem) + : m_fileSystem(fileSystem) { } @@ -175,11 +176,13 @@ SlangResult ArtifactContainerWriter::getBaseName(IArtifact* artifact, String& ou auto artifactName = artifact->getName(); if (artifactName && artifactName[0] != 0) { - baseName = ArtifactDescUtil::getBaseNameFromPath(artifactDesc, UnownedStringSlice(artifactName)); + baseName = ArtifactDescUtil::getBaseNameFromPath( + artifactDesc, + UnownedStringSlice(artifactName)); } } - // If we don't have name, use a generated one + // If we don't have name, use a generated one if (baseName.getLength() == 0) { baseName.append(m_entry.uniqueIndex++); @@ -194,7 +197,7 @@ SlangResult ArtifactContainerWriter::writeInDirectory(IArtifact* artifact, const // TODO(JS): // We could now output information about the desc/artifact, say as some json. // For now we assume the extension is good enough for most purposes. - + // If it's an "arbitrary" container, we don't need to write it if (artifact->getDesc().kind != ArtifactKind::Container) { @@ -204,7 +207,10 @@ SlangResult ArtifactContainerWriter::writeInDirectory(IArtifact* artifact, const // Get the name of the artifact StringBuilder artifactName; - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcNameForDesc(artifact->getDesc(), baseName.getUnownedSlice(), artifactName)); + SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcNameForDesc( + artifact->getDesc(), + baseName.getUnownedSlice(), + artifactName)); const auto combinedPath = Path::combine(m_entry.path, artifactName); // Write out the blob @@ -269,13 +275,22 @@ struct FileSystemContents struct IndexRange { SLANG_FORCE_INLINE Index getCount() const { return endIndex - startIndex; } - + SLANG_FORCE_INLINE Index begin() const { return startIndex; } SLANG_FORCE_INLINE Index end() const { return endIndex; } - void set(Index inStart, Index inEnd) { startIndex = inStart; endIndex = inEnd; } + void set(Index inStart, Index inEnd) + { + startIndex = inStart; + endIndex = inEnd; + } - static IndexRange make(Index inStart, Index inEnd) { IndexRange range; range.set(inStart, inEnd); return range; } + static IndexRange make(Index inStart, Index inEnd) + { + IndexRange range; + range.set(inStart, inEnd); + return range; + } Index startIndex; Index endIndex; @@ -289,7 +304,10 @@ struct FileSystemContents void setDirectory() { range.set(0, 0); } void setFile() { range.set(-1, -1); } - void setType(SlangPathType type) { (type == SLANG_PATH_TYPE_FILE) ? setFile() : setDirectory(); } + void setType(SlangPathType type) + { + (type == SLANG_PATH_TYPE_FILE) ? setFile() : setDirectory(); + } void setDirectoryRange(Index inStartIndex, Index inEndIndex) { @@ -298,33 +316,34 @@ struct FileSystemContents range.set(inStartIndex, inEndIndex); } - Index parentDirectoryIndex = -1; ///< The directory this entry is in. -1 is root. - UnownedStringSlice name; ///< Name of this entry - IndexRange range = IndexRange::make(-1, -1); ///< Default to file + Index parentDirectoryIndex = -1; ///< The directory this entry is in. -1 is root. + UnownedStringSlice name; ///< Name of this entry + IndexRange range = IndexRange::make(-1, -1); ///< Default to file }; - + void clear() { m_pool.clear(); m_entries.clear(); } - + IndexRange getContentsRange(Index index) const { return m_entries[index].range; } - - ConstArrayView getContents(Index index) const { return getContents(m_entries[index]); } + + ConstArrayView getContents(Index index) const { return getContents(m_entries[index]); } ConstArrayView getContents(const Entry& entry) const { - return entry.range.getCount() ? - makeConstArrayView(m_entries.getBuffer() + entry.range.startIndex, entry.range.getCount()) : - makeConstArrayView(nullptr, 0); + return entry.range.getCount() ? makeConstArrayView( + m_entries.getBuffer() + entry.range.startIndex, + entry.range.getCount()) + : makeConstArrayView(nullptr, 0); } - + void appendPath(Index entryIndex, StringBuilder& buf); SlangResult find(ISlangFileSystemExt* fileSyste, const UnownedStringSlice& path); - FileSystemContents(): - m_pool(StringSlicePool::Style::Default) + FileSystemContents() + : m_pool(StringSlicePool::Style::Default) { clear(); } @@ -334,7 +353,7 @@ struct FileSystemContents FileSystemContents* contents = (FileSystemContents*)userData; Entry entry; - + entry.parentDirectoryIndex = contents->m_currentParent; entry.name = contents->m_pool.addAndGetSlice(name); entry.setType(pathType); @@ -342,10 +361,10 @@ struct FileSystemContents contents->m_entries.add(entry); } - Index m_currentParent = -1; ///< Convenience for adding entries when using enumerate + Index m_currentParent = -1; ///< Convenience for adding entries when using enumerate - StringSlicePool m_pool; ///< Holds strings - List m_entries; ///< The entries + StringSlicePool m_pool; ///< Holds strings + List m_entries; ///< The entries }; void FileSystemContents::appendPath(Index entryIndex, StringBuilder& buf) @@ -366,7 +385,9 @@ void FileSystemContents::appendPath(Index entryIndex, StringBuilder& buf) buf.append(entry.name); } -SlangResult FileSystemContents::find(ISlangFileSystemExt* fileSystem, const UnownedStringSlice& inPath) +SlangResult FileSystemContents::find( + ISlangFileSystemExt* fileSystem, + const UnownedStringSlice& inPath) { clear(); @@ -400,7 +421,7 @@ SlangResult FileSystemContents::find(ISlangFileSystemExt* fileSystem, const Unow { Entry directoryEntry; directoryEntry.setDirectory(); - + directoryEntry.name = m_pool.addAndGetSlice(inPath); m_entries.add(directoryEntry); @@ -420,12 +441,12 @@ SlangResult FileSystemContents::find(ISlangFileSystemExt* fileSystem, const Unow const auto startIndex = m_entries.getCount(); - const char*const path = currentPath.getLength() ? currentPath.getBuffer() : "."; + const char* const path = currentPath.getLength() ? currentPath.getBuffer() : "."; const auto res = fileSystem->enumeratePathContents(path, _add, this); - + m_entries[i].setDirectoryRange(startIndex, m_entries.getCount()); - + SLANG_RETURN_ON_FAIL(res); } } @@ -436,12 +457,15 @@ SlangResult FileSystemContents::find(ISlangFileSystemExt* fileSystem, const Unow /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactContainerUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */SlangResult ArtifactContainerUtil::writeContainer(IArtifact* artifact, const String& defaultFileName, ISlangMutableFileSystem* fileSystem) +/* static */ SlangResult ArtifactContainerUtil::writeContainer( + IArtifact* artifact, + const String& defaultFileName, + ISlangMutableFileSystem* fileSystem) { ArtifactContainerWriter writer(fileSystem); String baseName; - + { const char* name = artifact->getName(); if (name == nullptr || name[0] == 0) @@ -454,9 +478,9 @@ SlangResult FileSystemContents::find(ISlangFileSystemExt* fileSystem, const Unow // If it's still not set try generating it. if (baseName.getLength() == 0) { - SLANG_RETURN_ON_FAIL(writer.getBaseName(artifact, baseName)); + SLANG_RETURN_ON_FAIL(writer.getBaseName(artifact, baseName)); } - + SLANG_RETURN_ON_FAIL(writer.writeInDirectory(artifact, baseName)); return SLANG_OK; @@ -472,7 +496,9 @@ static SlangResult _remove(ISlangMutableFileSystem* fileSystem, const String& pa return SLANG_OK; } -/* static */SlangResult ArtifactContainerUtil::writeContainer(IArtifact* artifact, const String& fileName) +/* static */ SlangResult ArtifactContainerUtil::writeContainer( + IArtifact* artifact, + const String& fileName) { auto osFileSystem = OSFileSystem::getMutableSingleton(); @@ -502,7 +528,7 @@ static SlangResult _remove(ISlangMutableFileSystem* fileSystem, const String& pa } else if (ext == toSlice("dir")) { - // We use the special extension "dir" to write out to a directory. + // We use the special extension "dir" to write out to a directory. // This is a little hokey arguably... auto path = Path::getPathWithoutExt(fileName); @@ -517,7 +543,8 @@ static SlangResult _remove(ISlangMutableFileSystem* fileSystem, const String& pa } // In order to write out as a artifact hierarchy we need a file system. If we don't have that - // we only write out the "main" (or root) artifact. All associated/children are typically ignored. + // we only write out the "main" (or root) artifact. All associated/children are typically + // ignored. { // Get the artifact as a blob ComPtr containerBlob; @@ -534,9 +561,12 @@ struct ArtifactContainerReader { SlangResult read(ISlangFileSystemExt* fileSystem, ComPtr& outArtifact); - /// A directory that contains multiple artifact directories - SlangResult _readContainerDirectory(Index directoryIndex, IArtifact::ContainedKind kind, IArtifact* container); - /// A directory that holds a single + /// A directory that contains multiple artifact directories + SlangResult _readContainerDirectory( + Index directoryIndex, + IArtifact::ContainedKind kind, + IArtifact* container); + /// A directory that holds a single SlangResult _readArtifactDirectory(Index directoryIndex, ComPtr& outArtifact); SlangResult _readFile(Index fileIndex, ComPtr& outArtifact); @@ -545,7 +575,9 @@ struct ArtifactContainerReader ISlangFileSystemExt* m_fileSystem; }; -SlangResult ArtifactContainerReader::read(ISlangFileSystemExt* fileSystem, ComPtr& outArtifact) +SlangResult ArtifactContainerReader::read( + ISlangFileSystemExt* fileSystem, + ComPtr& outArtifact) { m_fileSystem = fileSystem; m_contents.find(fileSystem, toSlice("")); @@ -556,7 +588,7 @@ SlangResult ArtifactContainerReader::read(ISlangFileSystemExt* fileSystem, ComPt SlangResult ArtifactContainerReader::_readFile(Index fileIndex, ComPtr& outArtifact) { outArtifact.setNull(); - + const auto& entry = m_contents.m_entries[fileIndex]; SLANG_ASSERT(entry.isFile()); @@ -565,8 +597,8 @@ SlangResult ArtifactContainerReader::_readFile(Index fileIndex, ComPtrsetName(entry.name.begin()); } @@ -608,17 +638,21 @@ SlangResult ArtifactContainerReader::_readFile(Index fileIndex, ComPtraddRepresentation(rep); - + outArtifact = artifact; return SLANG_OK; } -SlangResult ArtifactContainerReader::_readContainerDirectory(Index directoryIndex, IArtifact::ContainedKind kind, IArtifact* containerArtifact) +SlangResult ArtifactContainerReader::_readContainerDirectory( + Index directoryIndex, + IArtifact::ContainedKind kind, + IArtifact* containerArtifact) { // This directory only contains other directories which are artifacts - // Files are ignored + // Files are ignored auto indexRange = m_contents.getContentsRange(directoryIndex); @@ -635,14 +669,16 @@ SlangResult ArtifactContainerReader::_readContainerDirectory(Index directoryInde ComPtr artifact; SLANG_RETURN_ON_FAIL(_readArtifactDirectory(i, artifact)); - + if (artifact) { switch (kind) { - case IArtifact::ContainedKind::Associated: containerArtifact->addAssociated(artifact); break; - case IArtifact::ContainedKind::Children: containerArtifact->addChild(artifact); break; - default: SLANG_ASSERT(!"Can't add artifact to this kind"); return SLANG_FAIL; + case IArtifact::ContainedKind::Associated: + containerArtifact->addAssociated(artifact); + break; + case IArtifact::ContainedKind::Children: containerArtifact->addChild(artifact); break; + default: SLANG_ASSERT(!"Can't add artifact to this kind"); return SLANG_FAIL; } } } @@ -650,7 +686,9 @@ SlangResult ArtifactContainerReader::_readContainerDirectory(Index directoryInde return SLANG_OK; } -SlangResult ArtifactContainerReader::_readArtifactDirectory(Index directoryIndex, ComPtr& outArtifact) +SlangResult ArtifactContainerReader::_readArtifactDirectory( + Index directoryIndex, + ComPtr& outArtifact) { auto indexRange = m_contents.getContentsRange(directoryIndex); @@ -667,7 +705,7 @@ SlangResult ArtifactContainerReader::_readArtifactDirectory(Index directoryIndex { ComPtr readArtifact; SLANG_RETURN_ON_FAIL(_readFile(i, readArtifact)); - + if (readArtifact) { if (artifact) @@ -697,7 +735,8 @@ SlangResult ArtifactContainerReader::_readArtifactDirectory(Index directoryIndex // If we have children/associated we can assume it's a container if (childrenIndex >= 0 || associatedIndex >= 0) { - artifact = ArtifactUtil::createArtifact(ArtifactDesc::make(ArtifactKind::Container, ArtifactPayload::Unknown)); + artifact = ArtifactUtil::createArtifact( + ArtifactDesc::make(ArtifactKind::Container, ArtifactPayload::Unknown)); artifact->setName(m_contents.m_entries[directoryIndex].name.begin()); } else @@ -709,26 +748,32 @@ SlangResult ArtifactContainerReader::_readArtifactDirectory(Index directoryIndex if (childrenIndex >= 0) { - SLANG_RETURN_ON_FAIL(_readContainerDirectory(childrenIndex, IArtifact::ContainedKind::Children, artifact)); + SLANG_RETURN_ON_FAIL( + _readContainerDirectory(childrenIndex, IArtifact::ContainedKind::Children, artifact)); } if (associatedIndex >= 0) { - SLANG_RETURN_ON_FAIL(_readContainerDirectory(associatedIndex, IArtifact::ContainedKind::Associated, artifact)); + SLANG_RETURN_ON_FAIL(_readContainerDirectory( + associatedIndex, + IArtifact::ContainedKind::Associated, + artifact)); } outArtifact = artifact; return SLANG_OK; } -SlangResult ArtifactContainerUtil::readContainer(IArtifact* artifact, ComPtr& outArtifact) +SlangResult ArtifactContainerUtil::readContainer( + IArtifact* artifact, + ComPtr& outArtifact) { auto desc = artifact->getDesc(); ComPtr fileSystem; - + switch (desc.kind) { - case ArtifactKind::Zip: + case ArtifactKind::Zip: { SLANG_RETURN_ON_FAIL(ZipFileSystem::create(fileSystem)); @@ -741,10 +786,11 @@ SlangResult ArtifactContainerUtil::readContainer(IArtifact* artifact, ComPtr(fileSystem); SLANG_ASSERT(archiveFileSystem); - SLANG_RETURN_ON_FAIL(archiveFileSystem->loadArchive(blob->getBufferPointer(), blob->getBufferSize())); + SLANG_RETURN_ON_FAIL( + archiveFileSystem->loadArchive(blob->getBufferPointer(), blob->getBufferSize())); break; } - default: + default: { return SLANG_FAIL; } @@ -754,7 +800,9 @@ SlangResult ArtifactContainerUtil::readContainer(IArtifact* artifact, ComPtr& outArtifact) +/* static */ SlangResult ArtifactContainerUtil::readContainer( + ISlangFileSystemExt* fileSystem, + ComPtr& outArtifact) { SLANG_UNUSED(outArtifact); @@ -764,7 +812,9 @@ SlangResult ArtifactContainerUtil::readContainer(IArtifact* artifact, ComPtr& outArtifact) +/* static */ SlangResult ArtifactContainerUtil::filter( + IArtifact* artifact, + ComPtr& outArtifact) { outArtifact.setNull(); @@ -821,17 +871,15 @@ SlangResult ArtifactContainerUtil::readContainer(IArtifact* artifact, ComPtrgetChildren().count || - dstArtifact->getAssociated().count) + if (blob || dstArtifact->getChildren().count || dstArtifact->getAssociated().count) { outArtifact = dstArtifact; } - + // If we return an artifact or not, this was successful return SLANG_OK; } diff --git a/source/compiler-core/slang-artifact-container-util.h b/source/compiler-core/slang-artifact-container-util.h index eb0a12dfc..83090074e 100644 --- a/source/compiler-core/slang-artifact-container-util.h +++ b/source/compiler-core/slang-artifact-container-util.h @@ -3,43 +3,47 @@ #define SLANG_ARTIFACT_CONTAINER_UTIL_H #include "slang-artifact-representation.h" - #include "slang-com-helper.h" #include "slang-com-ptr.h" namespace Slang { -/* Functionality to save of and read artifact hierarchies via the slang +/* Functionality to save of and read artifact hierarchies via the slang artifact container style. This style treats storage as a file system. -Since this represention, is not directly a file system representation +Since this represention, is not directly a file system representation some conventions are used to associate data, via names etc. -The use of ISlangMutableFileSystem, allows writing this structure, to memory, zip, riff, directory +The use of ISlangMutableFileSystem, allows writing this structure, to memory, zip, riff, directory or other file like representations */ -struct ArtifactContainerUtil +struct ArtifactContainerUtil { - /// Write the container using the specified path. - /// Uses the extension of the path to determine how to write + /// Write the container using the specified path. + /// Uses the extension of the path to determine how to write static SlangResult writeContainer(IArtifact* artifact, const String& path); - /// If there isn't a suitable name on artifact, the filename is used to generate a name. If it's not set - /// a name may be generated. - static SlangResult writeContainer(IArtifact* artifact, const String& defaultFileName, ISlangMutableFileSystem* fileSystem); + /// If there isn't a suitable name on artifact, the filename is used to generate a name. If it's + /// not set a name may be generated. + static SlangResult writeContainer( + IArtifact* artifact, + const String& defaultFileName, + ISlangMutableFileSystem* fileSystem); - static SlangResult readContainer(ISlangFileSystemExt* fileSystem, ComPtr& outArtifact); + static SlangResult readContainer( + ISlangFileSystemExt* fileSystem, + ComPtr& outArtifact); - /// Read an artifact that represents a container as an artifact hierarchy + /// Read an artifact that represents a container as an artifact hierarchy static SlangResult readContainer(IArtifact* artifact, ComPtr& outArtifact); - /// Creates a copy of artifact where - /// * All artifacts are blobs - /// * Any generic containers that are empty are dropped - /// * Any sub artifact that can't be blobed and isn't significant is ignored - /// - /// A future improvement would be to take a function to also control what makes it to the output + /// Creates a copy of artifact where + /// * All artifacts are blobs + /// * Any generic containers that are empty are dropped + /// * Any sub artifact that can't be blobed and isn't significant is ignored + /// + /// A future improvement would be to take a function to also control what makes it to the output static SlangResult filter(IArtifact* artifact, ComPtr& outArtifact); }; diff --git a/source/compiler-core/slang-artifact-desc-util.cpp b/source/compiler-core/slang-artifact-desc-util.cpp index 7c2622f70..078398400 100644 --- a/source/compiler-core/slang-artifact-desc-util.cpp +++ b/source/compiler-core/slang-artifact-desc-util.cpp @@ -1,16 +1,16 @@ // slang-artifact-desc-util.cpp #include "slang-artifact-desc-util.h" -#include "slang-artifact-representation.h" - -#include "slang-artifact-impl.h" - -#include "../core/slang-type-text-util.h" #include "../core/slang-io.h" +#include "../core/slang-type-text-util.h" +#include "slang-artifact-impl.h" +#include "slang-artifact-representation.h" -namespace Slang { +namespace Slang +{ -namespace { // anonymous +namespace +{ // anonymous struct HierarchicalEnumEntry { @@ -61,7 +61,7 @@ static bool _isHierarchicalEnumOk(ConstArrayView entries, return true; } -template +template struct HierarchicalEnumTable { HierarchicalEnumTable(ConstArrayView entries) @@ -86,7 +86,7 @@ struct HierarchicalEnumTable m_names[value] = UnownedStringSlice(entry.name); } - // TODO(JS): NOTE! If we wanted to use parent to indicate if a value was *invalid* + // TODO(JS): NOTE! If we wanted to use parent to indicate if a value was *invalid* // we would want the Parent of Base to be Base. // // Base parent should be invalid @@ -95,17 +95,10 @@ struct HierarchicalEnumTable SLANG_ASSERT(getParent(T::Invalid) == T::Invalid); } - T getParent(T kind) const - { - return (kind >= T::CountOf) ? - T::Invalid : - m_parents[Index(kind)]; - } + T getParent(T kind) const { return (kind >= T::CountOf) ? T::Invalid : m_parents[Index(kind)]; } UnownedStringSlice getName(T kind) const { - return (kind >= T::CountOf) ? - UnownedStringSlice() : - m_names[Index(kind)]; + return (kind >= T::CountOf) ? UnownedStringSlice() : m_names[Index(kind)]; } bool isDerivedFrom(T type, T base) const @@ -132,25 +125,34 @@ protected: UnownedStringSlice m_names[Count(T::CountOf)]; }; -} // anonymous +} // namespace // Macro utils to create "enum hierarchy" tables -#define SLANG_HIERARCHICAL_ENUM_GET_VALUES(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_ENTRY_MACRO) \ -static ConstArrayView _getEntries##ENUM_TYPE() \ -{ \ - static const HierarchicalEnumEntry values[] = { ENUM_TYPE_MACRO(ENUM_ENTRY_MACRO) }; \ - return makeConstArrayView(values); \ -} - -#define SLANG_HIERARCHICAL_ENUM(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_VALUE_MACRO) \ -SLANG_HIERARCHICAL_ENUM_GET_VALUES(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_VALUE_MACRO) \ -\ -static const HierarchicalEnumTable g_table##ENUM_TYPE(_getEntries##ENUM_TYPE()); \ -\ -ENUM_TYPE getParent(ENUM_TYPE kind) { return g_table##ENUM_TYPE.getParent(kind); } \ -UnownedStringSlice getName(ENUM_TYPE kind) { return g_table##ENUM_TYPE.getName(kind); } \ -bool isDerivedFrom(ENUM_TYPE kind, ENUM_TYPE base) { return g_table##ENUM_TYPE.isDerivedFrom(kind, base); } +#define SLANG_HIERARCHICAL_ENUM_GET_VALUES(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_ENTRY_MACRO) \ + static ConstArrayView _getEntries##ENUM_TYPE() \ + { \ + static const HierarchicalEnumEntry values[] = {ENUM_TYPE_MACRO(ENUM_ENTRY_MACRO)}; \ + return makeConstArrayView(values); \ + } + +#define SLANG_HIERARCHICAL_ENUM(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_VALUE_MACRO) \ + SLANG_HIERARCHICAL_ENUM_GET_VALUES(ENUM_TYPE, ENUM_TYPE_MACRO, ENUM_VALUE_MACRO) \ + \ + static const HierarchicalEnumTable g_table##ENUM_TYPE(_getEntries##ENUM_TYPE()); \ + \ + ENUM_TYPE getParent(ENUM_TYPE kind) \ + { \ + return g_table##ENUM_TYPE.getParent(kind); \ + } \ + UnownedStringSlice getName(ENUM_TYPE kind) \ + { \ + return g_table##ENUM_TYPE.getName(kind); \ + } \ + bool isDerivedFrom(ENUM_TYPE kind, ENUM_TYPE base) \ + { \ + return g_table##ENUM_TYPE.isDerivedFrom(kind, base); \ + } /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactKind !!!!!!!!!!!!!!!!!!!!!!! */ @@ -245,117 +247,129 @@ SLANG_HIERARCHICAL_ENUM(ArtifactPayload, SLANG_ARTIFACT_PAYLOAD, SLANG_ARTIFACT_ x(CodeLike, Base) \ x(Kernel, CodeLike) \ x(Host, CodeLike) \ - x(Obfuscated, Base) + x(Obfuscated, Base) // clang-format on -#define SLANG_ARTIFACT_STYLE_ENTRY(TYPE, PARENT) { Index(ArtifactStyle::TYPE), Index(ArtifactStyle::PARENT), #TYPE }, +#define SLANG_ARTIFACT_STYLE_ENTRY(TYPE, PARENT) \ + {Index(ArtifactStyle::TYPE), Index(ArtifactStyle::PARENT), #TYPE}, SLANG_HIERARCHICAL_ENUM(ArtifactStyle, SLANG_ARTIFACT_STYLE, SLANG_ARTIFACT_STYLE_ENTRY) /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactDescUtil !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */ArtifactDesc ArtifactDescUtil::makeDescForCompileTarget(SlangCompileTarget target) +/* static */ ArtifactDesc ArtifactDescUtil::makeDescForCompileTarget(SlangCompileTarget target) { switch (target) { - case SLANG_TARGET_UNKNOWN: return Desc::make(Kind::Unknown, Payload::None, Style::Unknown, 0); - case SLANG_TARGET_NONE: return Desc::make(Kind::None, Payload::None, Style::Unknown, 0); - case SLANG_GLSL: + case SLANG_TARGET_UNKNOWN: return Desc::make(Kind::Unknown, Payload::None, Style::Unknown, 0); + case SLANG_TARGET_NONE: return Desc::make(Kind::None, Payload::None, Style::Unknown, 0); + case SLANG_GLSL: { // For the moment we Desc::make all just map to GLSL, but we could use flags // or some other mechanism to distinguish the types return Desc::make(Kind::Source, Payload::GLSL, Style::Kernel, 0); } - case SLANG_HLSL: return Desc::make(Kind::Source, Payload::HLSL, Style::Kernel, 0); - case SLANG_SPIRV: return Desc::make(Kind::ObjectCode, Payload::SPIRV, Style::Kernel, 0); - case SLANG_SPIRV_ASM: return Desc::make(Kind::Assembly, Payload::SPIRV, Style::Kernel, 0); - case SLANG_DXBC: return Desc::make(Kind::ObjectCode, Payload::DXBC, Style::Kernel, 0); - case SLANG_DXBC_ASM: return Desc::make(Kind::Assembly, Payload::DXBC, Style::Kernel, 0); - case SLANG_DXIL: return Desc::make(Kind::ObjectCode, Payload::DXIL, Style::Kernel, 0); - case SLANG_DXIL_ASM: return Desc::make(Kind::Assembly, Payload::DXIL, Style::Kernel, 0); - case SLANG_C_SOURCE: return Desc::make(Kind::Source, Payload::C, Style::Kernel, 0); - case SLANG_CPP_SOURCE: return Desc::make(Kind::Source, Payload::Cpp, Style::Kernel, 0); - case SLANG_HOST_CPP_SOURCE: return Desc::make(Kind::Source, Payload::Cpp, Style::Host, 0); - case SLANG_CPP_PYTORCH_BINDING: return Desc::make(Kind::Source, Payload::Cpp, Style::Host, 0); - case SLANG_HOST_EXECUTABLE: return Desc::make(Kind::Executable, Payload::HostCPU, Style::Host, 0); - case SLANG_HOST_SHARED_LIBRARY: return Desc::make(Kind::SharedLibrary, Payload::HostCPU, Style::Host, 0); - case SLANG_SHADER_SHARED_LIBRARY: return Desc::make(Kind::SharedLibrary, Payload::HostCPU, Style::Kernel, 0); - case SLANG_SHADER_HOST_CALLABLE: return Desc::make(Kind::HostCallable, Payload::HostCPU, Style::Kernel, 0); - case SLANG_CUDA_SOURCE: return Desc::make(Kind::Source, Payload::CUDA, Style::Kernel, 0); - // TODO(JS): - // Not entirely clear how best to represent PTX here. We could mark as 'Assembly'. Saying it is - // 'Executable' implies it is Binary (which PTX isn't). Executable also implies 'complete for executation', - // irrespective of it being text. - case SLANG_PTX: return Desc::make(Kind::ObjectCode, Payload::PTX, Style::Kernel, 0); - case SLANG_OBJECT_CODE: return Desc::make(Kind::ObjectCode, Payload::HostCPU, Style::Kernel, 0); - case SLANG_HOST_HOST_CALLABLE: return Desc::make(Kind::HostCallable, Payload::HostCPU, Style::Host, 0); - case SLANG_METAL: return Desc::make(Kind::Source, Payload::Metal, Style::Kernel, 0); - case SLANG_METAL_LIB: return Desc::make(Kind::ObjectCode, Payload::MetalAIR, Style::Kernel, 0); - case SLANG_METAL_LIB_ASM: return Desc::make(Kind::Assembly, Payload::MetalAIR, Style::Kernel, 0); - case SLANG_WGSL: return Desc::make(Kind::Source, Payload::WGSL, Style::Kernel, 0); - case SLANG_WGSL_SPIRV_ASM: return Desc::make(Kind::Assembly, Payload::WGSL_SPIRV, Style::Kernel, 0); - case SLANG_WGSL_SPIRV: return Desc::make(Kind::ObjectCode, Payload::WGSL_SPIRV, Style::Kernel, 0); - default: break; + case SLANG_HLSL: return Desc::make(Kind::Source, Payload::HLSL, Style::Kernel, 0); + case SLANG_SPIRV: return Desc::make(Kind::ObjectCode, Payload::SPIRV, Style::Kernel, 0); + case SLANG_SPIRV_ASM: return Desc::make(Kind::Assembly, Payload::SPIRV, Style::Kernel, 0); + case SLANG_DXBC: return Desc::make(Kind::ObjectCode, Payload::DXBC, Style::Kernel, 0); + case SLANG_DXBC_ASM: return Desc::make(Kind::Assembly, Payload::DXBC, Style::Kernel, 0); + case SLANG_DXIL: return Desc::make(Kind::ObjectCode, Payload::DXIL, Style::Kernel, 0); + case SLANG_DXIL_ASM: return Desc::make(Kind::Assembly, Payload::DXIL, Style::Kernel, 0); + case SLANG_C_SOURCE: return Desc::make(Kind::Source, Payload::C, Style::Kernel, 0); + case SLANG_CPP_SOURCE: return Desc::make(Kind::Source, Payload::Cpp, Style::Kernel, 0); + case SLANG_HOST_CPP_SOURCE: return Desc::make(Kind::Source, Payload::Cpp, Style::Host, 0); + case SLANG_CPP_PYTORCH_BINDING: return Desc::make(Kind::Source, Payload::Cpp, Style::Host, 0); + case SLANG_HOST_EXECUTABLE: + return Desc::make(Kind::Executable, Payload::HostCPU, Style::Host, 0); + case SLANG_HOST_SHARED_LIBRARY: + return Desc::make(Kind::SharedLibrary, Payload::HostCPU, Style::Host, 0); + case SLANG_SHADER_SHARED_LIBRARY: + return Desc::make(Kind::SharedLibrary, Payload::HostCPU, Style::Kernel, 0); + case SLANG_SHADER_HOST_CALLABLE: + return Desc::make(Kind::HostCallable, Payload::HostCPU, Style::Kernel, 0); + case SLANG_CUDA_SOURCE: + return Desc::make(Kind::Source, Payload::CUDA, Style::Kernel, 0); + // TODO(JS): + // Not entirely clear how best to represent PTX here. We could mark as 'Assembly'. + // Saying it is 'Executable' implies it is Binary (which PTX isn't). Executable also + // implies 'complete for executation', irrespective of it being text. + case SLANG_PTX: return Desc::make(Kind::ObjectCode, Payload::PTX, Style::Kernel, 0); + case SLANG_OBJECT_CODE: return Desc::make(Kind::ObjectCode, Payload::HostCPU, Style::Kernel, 0); + case SLANG_HOST_HOST_CALLABLE: + return Desc::make(Kind::HostCallable, Payload::HostCPU, Style::Host, 0); + case SLANG_METAL: return Desc::make(Kind::Source, Payload::Metal, Style::Kernel, 0); + case SLANG_METAL_LIB: return Desc::make(Kind::ObjectCode, Payload::MetalAIR, Style::Kernel, 0); + case SLANG_METAL_LIB_ASM: + return Desc::make(Kind::Assembly, Payload::MetalAIR, Style::Kernel, 0); + case SLANG_WGSL: return Desc::make(Kind::Source, Payload::WGSL, Style::Kernel, 0); + case SLANG_WGSL_SPIRV_ASM: + return Desc::make(Kind::Assembly, Payload::WGSL_SPIRV, Style::Kernel, 0); + case SLANG_WGSL_SPIRV: + return Desc::make(Kind::ObjectCode, Payload::WGSL_SPIRV, Style::Kernel, 0); + default: break; } SLANG_UNEXPECTED("Unhandled type"); } -/* static */ArtifactPayload ArtifactDescUtil::getPayloadForSourceLanaguage(SlangSourceLanguage language) +/* static */ ArtifactPayload ArtifactDescUtil::getPayloadForSourceLanaguage( + SlangSourceLanguage language) { switch (language) { - default: - case SLANG_SOURCE_LANGUAGE_UNKNOWN: return Payload::Unknown; - case SLANG_SOURCE_LANGUAGE_SLANG: return Payload::Slang; - case SLANG_SOURCE_LANGUAGE_HLSL: return Payload::HLSL; - case SLANG_SOURCE_LANGUAGE_GLSL: return Payload::GLSL; - case SLANG_SOURCE_LANGUAGE_C: return Payload::C; - case SLANG_SOURCE_LANGUAGE_CPP: return Payload::Cpp; - case SLANG_SOURCE_LANGUAGE_CUDA: return Payload::CUDA; + default: + case SLANG_SOURCE_LANGUAGE_UNKNOWN: return Payload::Unknown; + case SLANG_SOURCE_LANGUAGE_SLANG: return Payload::Slang; + case SLANG_SOURCE_LANGUAGE_HLSL: return Payload::HLSL; + case SLANG_SOURCE_LANGUAGE_GLSL: return Payload::GLSL; + case SLANG_SOURCE_LANGUAGE_C: return Payload::C; + case SLANG_SOURCE_LANGUAGE_CPP: return Payload::Cpp; + case SLANG_SOURCE_LANGUAGE_CUDA: return Payload::CUDA; } } -/* static */ArtifactDesc ArtifactDescUtil::makeDescForSourceLanguage(SlangSourceLanguage language) +/* static */ ArtifactDesc ArtifactDescUtil::makeDescForSourceLanguage(SlangSourceLanguage language) { return Desc::make(Kind::Source, getPayloadForSourceLanaguage(language), Style::Unknown, 0); } -/* static */SlangCompileTarget ArtifactDescUtil::getCompileTargetFromDesc(const ArtifactDesc& desc) +/* static */ SlangCompileTarget ArtifactDescUtil::getCompileTargetFromDesc(const ArtifactDesc& desc) { switch (desc.kind) { - case ArtifactKind::None: return SLANG_TARGET_NONE; - case ArtifactKind::Source: + case ArtifactKind::None: return SLANG_TARGET_NONE; + case ArtifactKind::Source: { switch (desc.payload) { - case Payload::HLSL: return SLANG_HLSL; - case Payload::GLSL: return SLANG_GLSL; - case Payload::C: return SLANG_C_SOURCE; - case Payload::Cpp: return (desc.style == Style::Host) ? SLANG_HOST_CPP_SOURCE : SLANG_CPP_SOURCE; - case Payload::CUDA: return SLANG_CUDA_SOURCE; - case Payload::Metal: return SLANG_METAL; - case Payload::WGSL: return SLANG_WGSL; - default: break; + case Payload::HLSL: return SLANG_HLSL; + case Payload::GLSL: return SLANG_GLSL; + case Payload::C: return SLANG_C_SOURCE; + case Payload::Cpp: + return (desc.style == Style::Host) ? SLANG_HOST_CPP_SOURCE : SLANG_CPP_SOURCE; + case Payload::CUDA: return SLANG_CUDA_SOURCE; + case Payload::Metal: return SLANG_METAL; + case Payload::WGSL: return SLANG_WGSL; + default: break; } break; } - case ArtifactKind::Assembly: + case ArtifactKind::Assembly: { switch (desc.payload) { - case Payload::SPIRV: return SLANG_SPIRV_ASM; - case Payload::DXIL: return SLANG_DXIL_ASM; - case Payload::DXBC: return SLANG_DXBC_ASM; - case Payload::PTX: return SLANG_PTX; - case Payload::MetalAIR: return SLANG_METAL_LIB_ASM; - case Payload::WGSL_SPIRV: return SLANG_WGSL_SPIRV_ASM; - default: break; + case Payload::SPIRV: return SLANG_SPIRV_ASM; + case Payload::DXIL: return SLANG_DXIL_ASM; + case Payload::DXBC: return SLANG_DXBC_ASM; + case Payload::PTX: return SLANG_PTX; + case Payload::MetalAIR: return SLANG_METAL_LIB_ASM; + case Payload::WGSL_SPIRV: return SLANG_WGSL_SPIRV_ASM; + default: break; } } - default: break; + default: break; } if (isDerivedFrom(desc.kind, ArtifactKind::CompileBinary)) @@ -364,24 +378,28 @@ SLANG_HIERARCHICAL_ENUM(ArtifactStyle, SLANG_ARTIFACT_STYLE, SLANG_ARTIFACT_STYL { switch (desc.kind) { - case Kind::Executable: return SLANG_HOST_EXECUTABLE; - case Kind::SharedLibrary: return desc.style == ArtifactStyle::Host ? SLANG_HOST_SHARED_LIBRARY : SLANG_SHADER_SHARED_LIBRARY; - case Kind::HostCallable: return desc.style == ArtifactStyle::Host ? SLANG_HOST_HOST_CALLABLE : SLANG_SHADER_HOST_CALLABLE; - case Kind::ObjectCode: return SLANG_OBJECT_CODE; - default: break; + case Kind::Executable: return SLANG_HOST_EXECUTABLE; + case Kind::SharedLibrary: + return desc.style == ArtifactStyle::Host ? SLANG_HOST_SHARED_LIBRARY + : SLANG_SHADER_SHARED_LIBRARY; + case Kind::HostCallable: + return desc.style == ArtifactStyle::Host ? SLANG_HOST_HOST_CALLABLE + : SLANG_SHADER_HOST_CALLABLE; + case Kind::ObjectCode: return SLANG_OBJECT_CODE; + default: break; } } else { switch (desc.payload) { - case Payload::SPIRV: return SLANG_SPIRV; - case Payload::DXIL: return SLANG_DXIL; - case Payload::DXBC: return SLANG_DXBC; - case Payload::PTX: return SLANG_PTX; - case Payload::MetalAIR: return SLANG_METAL_LIB_ASM; - case Payload::WGSL_SPIRV: return SLANG_WGSL_SPIRV; - default: break; + case Payload::SPIRV: return SLANG_SPIRV; + case Payload::DXIL: return SLANG_DXIL; + case Payload::DXBC: return SLANG_DXBC; + case Payload::PTX: return SLANG_PTX; + case Payload::MetalAIR: return SLANG_METAL_LIB_ASM; + case Payload::WGSL_SPIRV: return SLANG_WGSL_SPIRV; + default: break; } } } @@ -390,35 +408,31 @@ SLANG_HIERARCHICAL_ENUM(ArtifactStyle, SLANG_ARTIFACT_STYLE, SLANG_ARTIFACT_STYL } -namespace { // anonymous +namespace +{ // anonymous struct KindExtension { ArtifactKind kind; UnownedStringSlice ext; }; -} // anonymous +} // namespace -#define SLANG_KIND_EXTENSION(kind, ext) \ - { ArtifactKind::kind, toSlice(ext) }, +#define SLANG_KIND_EXTENSION(kind, ext) {ArtifactKind::kind, toSlice(ext)}, -static const KindExtension g_cpuKindExts[] = -{ +static const KindExtension g_cpuKindExts[] = { #if SLANG_WINDOWS_FAMILY - SLANG_KIND_EXTENSION(Library, "lib") - SLANG_KIND_EXTENSION(ObjectCode, "obj") - SLANG_KIND_EXTENSION(Executable, "exe") - SLANG_KIND_EXTENSION(SharedLibrary, "dll") -#else - SLANG_KIND_EXTENSION(Library, "a") - SLANG_KIND_EXTENSION(ObjectCode, "o") - SLANG_KIND_EXTENSION(Executable, "") + SLANG_KIND_EXTENSION(Library, "lib") SLANG_KIND_EXTENSION(ObjectCode, "obj") + SLANG_KIND_EXTENSION(Executable, "exe") SLANG_KIND_EXTENSION(SharedLibrary, "dll") +#else + SLANG_KIND_EXTENSION(Library, "a") SLANG_KIND_EXTENSION(ObjectCode, "o") + SLANG_KIND_EXTENSION(Executable, "") #if __CYGWIN__ - SLANG_KIND_EXTENSION(SharedLibrary, "dll") + SLANG_KIND_EXTENSION(SharedLibrary, "dll") #elif SLANG_APPLE_FAMILY - SLANG_KIND_EXTENSION(SharedLibrary, "dylib") + SLANG_KIND_EXTENSION(SharedLibrary, "dylib") #else - SLANG_KIND_EXTENSION(SharedLibrary, "so") + SLANG_KIND_EXTENSION(SharedLibrary, "so") #endif #endif @@ -426,10 +440,11 @@ static const KindExtension g_cpuKindExts[] = /* static */ bool ArtifactDescUtil::isCpuBinary(const ArtifactDesc& desc) { - return isDerivedFrom(desc.kind, ArtifactKind::CompileBinary) && isDerivedFrom(desc.payload, ArtifactPayload::CPULike); + return isDerivedFrom(desc.kind, ArtifactKind::CompileBinary) && + isDerivedFrom(desc.payload, ArtifactPayload::CPULike); } -/* static */bool ArtifactDescUtil::isText(const ArtifactDesc& desc) +/* static */ bool ArtifactDescUtil::isText(const ArtifactDesc& desc) { // If it's derived from text... if (isDerivedFrom(desc.kind, ArtifactKind::Text)) @@ -447,33 +462,33 @@ static const KindExtension g_cpuKindExts[] = return false; } -/* static */bool ArtifactDescUtil::isGpuUsable(const ArtifactDesc& desc) +/* static */ bool ArtifactDescUtil::isGpuUsable(const ArtifactDesc& desc) { if (isDerivedFrom(desc.kind, ArtifactKind::CompileBinary)) { return isDerivedFrom(desc.payload, ArtifactPayload::KernelLike); } - // PTX is a kind of special case, it's an 'assembly' (low level text represention) that can be passed - // to CUDA runtime + // PTX is a kind of special case, it's an 'assembly' (low level text represention) that can be + // passed to CUDA runtime return desc.kind == ArtifactKind::Assembly && desc.payload == ArtifactPayload::PTX; } -/* static */bool ArtifactDescUtil::isKindBinaryLinkable(Kind kind) +/* static */ bool ArtifactDescUtil::isKindBinaryLinkable(Kind kind) { switch (kind) { - case Kind::Library: - case Kind::ObjectCode: + case Kind::Library: + case Kind::ObjectCode: { return true; } - default: break; + default: break; } return false; } -/* static */bool ArtifactDescUtil::isLinkable(const ArtifactDesc& desc) +/* static */ bool ArtifactDescUtil::isLinkable(const ArtifactDesc& desc) { // If is a container with compile results *assume* that result is linkable if (isDerivedFrom(desc.kind, ArtifactKind::Container) && @@ -483,7 +498,7 @@ static const KindExtension g_cpuKindExts[] = } // if it's a compile binary or a container - if (isDerivedFrom(desc.kind, ArtifactKind::CompileBinary)) + if (isDerivedFrom(desc.kind, ArtifactKind::CompileBinary)) { if (isDerivedFrom(desc.payload, ArtifactPayload::KernelLike)) { @@ -498,8 +513,7 @@ static const KindExtension g_cpuKindExts[] = else if (isDerivedFrom(desc.payload, ArtifactPayload::CPULike)) { // If kind is exe or shared library, linking will arguably not work - if (desc.kind == ArtifactKind::SharedLibrary || - desc.kind == ArtifactKind::Executable) + if (desc.kind == ArtifactKind::SharedLibrary || desc.kind == ArtifactKind::Executable) { return false; } @@ -515,7 +529,7 @@ static const KindExtension g_cpuKindExts[] = return false; } -/* static */bool ArtifactDescUtil::isCpuLikeTarget(const ArtifactDesc& desc) +/* static */ bool ArtifactDescUtil::isCpuLikeTarget(const ArtifactDesc& desc) { if (isDerivedFrom(desc.kind, ArtifactKind::CompileBinary)) { @@ -530,10 +544,9 @@ static const KindExtension g_cpuKindExts[] = return false; } -/* static */ArtifactDesc ArtifactDescUtil::getDescFromExtension(const UnownedStringSlice& slice) +/* static */ ArtifactDesc ArtifactDescUtil::getDescFromExtension(const UnownedStringSlice& slice) { - if (slice == "slang-module" || - slice == "slang-lib") + if (slice == "slang-module" || slice == "slang-lib") { return ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::SlangIR); } @@ -577,7 +590,7 @@ static const KindExtension g_cpuKindExts[] = return ArtifactDesc::make(ArtifactKind::Assembly, ArtifactPayload::HostCPU); } - // TODO(JS): Unfortunately map extension is also used from output for linkage from + // TODO(JS): Unfortunately map extension is also used from output for linkage from // Visual Studio. It's used here for source map. if (slice == toSlice("map")) { @@ -604,7 +617,7 @@ static const KindExtension g_cpuKindExts[] = return makeDescForCompileTarget(target); } -/* static */ArtifactDesc ArtifactDescUtil::getDescFromPath(const UnownedStringSlice& slice) +/* static */ ArtifactDesc ArtifactDescUtil::getDescFromPath(const UnownedStringSlice& slice) { auto extension = Path::getPathExt(slice); return getDescFromExtension(extension); @@ -628,36 +641,36 @@ static UnownedStringSlice _getPayloadExtension(ArtifactPayload payload) typedef ArtifactPayload Payload; switch (payload) { - /* Source types */ - case Payload::HLSL: return toSlice("hlsl"); - case Payload::GLSL: return toSlice("glsl"); + /* Source types */ + case Payload::HLSL: return toSlice("hlsl"); + case Payload::GLSL: return toSlice("glsl"); - case Payload::Cpp: return toSlice("cpp"); - case Payload::C: return toSlice("c"); + case Payload::Cpp: return toSlice("cpp"); + case Payload::C: return toSlice("c"); - case Payload::Metal: return toSlice("metal"); + case Payload::Metal: return toSlice("metal"); - case Payload::CUDA: return toSlice("cu"); + case Payload::CUDA: return toSlice("cu"); - case Payload::Slang: return toSlice("slang"); + case Payload::Slang: return toSlice("slang"); - /* Binary types */ - case Payload::DXIL: return toSlice("dxil"); - case Payload::DXBC: return toSlice("dxbc"); - case Payload::SPIRV: return toSlice("spv"); + /* Binary types */ + case Payload::DXIL: return toSlice("dxil"); + case Payload::DXBC: return toSlice("dxbc"); + case Payload::SPIRV: return toSlice("spv"); - case Payload::PTX: return toSlice("ptx"); + case Payload::PTX: return toSlice("ptx"); - case Payload::LLVMIR: return toSlice("llvm-ir"); + case Payload::LLVMIR: return toSlice("llvm-ir"); - case Payload::SlangIR: return toSlice("slang-ir"); - - case Payload::MetalAIR: return toSlice("metallib"); + case Payload::SlangIR: return toSlice("slang-ir"); - case Payload::PdbDebugInfo: return toSlice("pdb"); - case Payload::SourceMap: return toSlice("map"); + case Payload::MetalAIR: return toSlice("metallib"); - default: break; + case Payload::PdbDebugInfo: return toSlice("pdb"); + case Payload::SourceMap: return toSlice("map"); + + default: break; } return UnownedStringSlice(); } @@ -666,7 +679,7 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S { switch (desc.kind) { - case ArtifactKind::Library: + case ArtifactKind::Library: { // Special cases if (desc.payload == Payload::SlangIR) @@ -680,30 +693,30 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S out << toSlice("metallib"); return SLANG_OK; } - + break; } - case ArtifactKind::Zip: + case ArtifactKind::Zip: { out << toSlice("zip"); return SLANG_OK; } - case ArtifactKind::RiffContainer: + case ArtifactKind::RiffContainer: { out << toSlice("riff"); return SLANG_OK; } - case ArtifactKind::RiffLz4Container: + case ArtifactKind::RiffLz4Container: { out << toSlice("riff-lz4"); return SLANG_OK; } - case ArtifactKind::RiffDeflateContainer: + case ArtifactKind::RiffDeflateContainer: { out << toSlice("riff-deflate"); return SLANG_OK; } - case ArtifactKind::Assembly: + case ArtifactKind::Assembly: { // Special case PTX, because it is assembly if (desc.payload == Payload::PTX) @@ -724,7 +737,7 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S out << toSlice("-asm"); return SLANG_OK; } - case ArtifactKind::Source: + case ArtifactKind::Source: { auto ext = _getPayloadExtension(desc.payload); if (ext.begin() != nullptr) @@ -732,10 +745,10 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S out << ext; return SLANG_OK; } - // Don't know the extension for that + // Don't know the extension for that return SLANG_E_NOT_FOUND; } - case ArtifactKind::Json: + case ArtifactKind::Json: { auto ext = _getPayloadExtension(desc.payload); if (ext.begin() != nullptr) @@ -743,8 +756,8 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S // TODO(JS): // Do we need to alter the extension or the name if it's an // obfuscated map? - //if (isDerivedFrom(desc.style, ArtifactStyle::Obfuscated)) - //{ + // if (isDerivedFrom(desc.style, ArtifactStyle::Obfuscated)) + //{ //} out << ext; @@ -755,7 +768,7 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S out << "json"; return SLANG_OK; } - case ArtifactKind::CompileBinary: + case ArtifactKind::CompileBinary: { if (isDerivedFrom(desc.payload, ArtifactPayload::SlangIR) || isDerivedFrom(desc.payload, ArtifactPayload::SlangAST)) @@ -765,7 +778,7 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S } break; } - default: break; + default: break; } if (ArtifactDescUtil::isGpuUsable(desc)) @@ -778,21 +791,26 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S } } - if (ArtifactDescUtil::isCpuLikeTarget(desc) && !isDerivedFrom(desc.payload, ArtifactPayload::Source)) + if (ArtifactDescUtil::isCpuLikeTarget(desc) && + !isDerivedFrom(desc.payload, ArtifactPayload::Source)) { return appendCpuExtensionForKind(desc.kind, out); } - + return SLANG_E_NOT_FOUND; } -/* static */String ArtifactDescUtil::getBaseNameFromPath(const ArtifactDesc& desc, const UnownedStringSlice& path) +/* static */ String ArtifactDescUtil::getBaseNameFromPath( + const ArtifactDesc& desc, + const UnownedStringSlice& path) { const String name = Path::getFileName(path); return getBaseNameFromName(desc, name.getUnownedSlice()); } -/* static */String ArtifactDescUtil::getBaseNameFromName(const ArtifactDesc& desc, const UnownedStringSlice& inName) +/* static */ String ArtifactDescUtil::getBaseNameFromName( + const ArtifactDesc& desc, + const UnownedStringSlice& inName) { String name(inName); @@ -801,8 +819,7 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S { // Strip lib prefix if (isCpuBinary(desc) && - (desc.kind == ArtifactKind::Library || - desc.kind == ArtifactKind::SharedLibrary)) + (desc.kind == ArtifactKind::Library || desc.kind == ArtifactKind::SharedLibrary)) { // If it starts with lib strip it if (name.startsWith("lib")) @@ -816,12 +833,11 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S // Strip any extension { StringBuilder descExt; - if (SLANG_SUCCEEDED(appendDefaultExtension(desc, descExt)) && - descExt.getLength()) + if (SLANG_SUCCEEDED(appendDefaultExtension(desc, descExt)) && descExt.getLength()) { - // TODO(JS): + // TODO(JS): // It has an extension. We could check if they are the same - // but if they are not that might be fine, because of case insensitivity + // but if they are not that might be fine, because of case insensitivity // or perhaps there are multiple valid extensions. So for now we just strip // and don't bother confirming with something like.. // if (Path::getPathExt(name) == descExt)) @@ -833,19 +849,24 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S return name; } -/* static */String ArtifactDescUtil::getBaseName(const ArtifactDesc& desc, IPathArtifactRepresentation* pathRep) +/* static */ String ArtifactDescUtil::getBaseName( + const ArtifactDesc& desc, + IPathArtifactRepresentation* pathRep) { UnownedStringSlice path(pathRep->getPath()); return getBaseNameFromPath(desc, path); } -/* static */SlangResult ArtifactDescUtil::hasDefinedNameForDesc(const ArtifactDesc& desc) +/* static */ SlangResult ArtifactDescUtil::hasDefinedNameForDesc(const ArtifactDesc& desc) { StringBuilder buf; return SLANG_SUCCEEDED(appendDefaultExtension(desc, buf)); } -/* static */SlangResult ArtifactDescUtil::calcNameForDesc(const ArtifactDesc& desc, const UnownedStringSlice& inBaseName, StringBuilder& outName) +/* static */ SlangResult ArtifactDescUtil::calcNameForDesc( + const ArtifactDesc& desc, + const UnownedStringSlice& inBaseName, + StringBuilder& outName) { UnownedStringSlice baseName(inBaseName); @@ -857,8 +878,7 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S // Prefix if (isCpuBinary(desc) && - (desc.kind == ArtifactKind::SharedLibrary || - desc.kind == ArtifactKind::Library)) + (desc.kind == ArtifactKind::SharedLibrary || desc.kind == ArtifactKind::Library)) { const bool isSharedLibraryPrefixPlatform = SLANG_LINUX_FAMILY || SLANG_APPLE_FAMILY; if (isSharedLibraryPrefixPlatform) @@ -889,7 +909,10 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S return SLANG_OK; } -/* static */SlangResult ArtifactDescUtil::calcPathForDesc(const ArtifactDesc& desc, const UnownedStringSlice& basePath, StringBuilder& outPath) +/* static */ SlangResult ArtifactDescUtil::calcPathForDesc( + const ArtifactDesc& desc, + const UnownedStringSlice& basePath, + StringBuilder& outPath) { outPath.clear(); @@ -914,18 +937,17 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S } } -/* static */bool ArtifactDescUtil::isDisassembly(const ArtifactDesc& from, const ArtifactDesc& to) +/* static */ bool ArtifactDescUtil::isDisassembly(const ArtifactDesc& from, const ArtifactDesc& to) { // From must be a binary like type if (!isDerivedFrom(from.kind, ArtifactKind::CompileBinary)) { return false; } - - + + // Target must be assembly, and the payload be the same type - if (!(to.kind == ArtifactKind::Assembly && - to.payload == from.payload)) + if (!(to.kind == ArtifactKind::Assembly && to.payload == from.payload)) { return false; } @@ -934,15 +956,14 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S // Check the payload seems like something plausible to 'disassemble' if (!(isDerivedFrom(payload, ArtifactPayload::KernelLike) || - isDerivedFrom(payload, ArtifactPayload::CPULike) || - isDerivedFrom(payload, ArtifactPayload::GeneralIR))) + isDerivedFrom(payload, ArtifactPayload::CPULike) || + isDerivedFrom(payload, ArtifactPayload::GeneralIR))) { return false; } // If the flags or style are different, then it's something more than just disassembly - if (!(from.style == to.style && - from.flags == to.flags)) + if (!(from.style == to.style && from.flags == to.flags)) { return false; } @@ -950,13 +971,13 @@ SlangResult ArtifactDescUtil::appendDefaultExtension(const ArtifactDesc& desc, S return true; } -/* static */void ArtifactDescUtil::appendText(const ArtifactDesc& desc, StringBuilder& out) +/* static */ void ArtifactDescUtil::appendText(const ArtifactDesc& desc, StringBuilder& out) { out << getName(desc.kind) << "/" << getName(desc.payload) << "/" << getName(desc.style); // TODO(JS): Output flags? None currently used } -/* static */String ArtifactDescUtil::getText(const ArtifactDesc& desc) +/* static */ String ArtifactDescUtil::getText(const ArtifactDesc& desc) { StringBuilder buf; appendText(desc, buf); diff --git a/source/compiler-core/slang-artifact-desc-util.h b/source/compiler-core/slang-artifact-desc-util.h index 879732bb1..0c513474b 100644 --- a/source/compiler-core/slang-artifact-desc-util.h +++ b/source/compiler-core/slang-artifact-desc-util.h @@ -8,25 +8,25 @@ namespace Slang { - /// Get the parent kind +/// Get the parent kind ArtifactKind getParent(ArtifactKind kind); - /// Returns true if kind is derived from base +/// Returns true if kind is derived from base bool isDerivedFrom(ArtifactKind kind, ArtifactKind base); - /// Get the name for the kind +/// Get the name for the kind UnownedStringSlice getName(ArtifactKind kind); - /// Get the parent payload -ArtifactPayload getParent(ArtifactPayload payload); - /// Returns true if payload is derived from base +/// Get the parent payload +ArtifactPayload getParent(ArtifactPayload payload); +/// Returns true if payload is derived from base bool isDerivedFrom(ArtifactPayload payload, ArtifactPayload base); - /// Get the name for the payload +/// Get the name for the payload UnownedStringSlice getName(ArtifactPayload payload); - /// Get the parent style +/// Get the parent style ArtifactStyle getParent(ArtifactStyle style); - /// Returns true if style is derived from base +/// Returns true if style is derived from base bool isDerivedFrom(ArtifactStyle style, ArtifactStyle base); - /// Get the name for the style +/// Get the name for the style UnownedStringSlice getName(ArtifactStyle style); struct ArtifactDescUtil @@ -35,89 +35,95 @@ struct ArtifactDescUtil typedef ArtifactKind Kind; typedef ArtifactStyle Style; typedef ArtifactDesc Desc; - - /// Returns true if the kind is binary linkable + + /// Returns true if the kind is binary linkable static bool isKindBinaryLinkable(Kind kind); - /// True if is a CPU target - either + /// True if is a CPU target - either static bool isCpuLikeTarget(const ArtifactDesc& desc); - /// True if is a CPU binary + /// True if is a CPU binary static bool isCpuBinary(const ArtifactDesc& desc); - /// True if is a GPU usable (can be passed to a driver/API and be used) + /// True if is a GPU usable (can be passed to a driver/API and be used) static bool isGpuUsable(const ArtifactDesc& desc); - /// True if the desc holds textual information + /// True if the desc holds textual information static bool isText(const ArtifactDesc& desc); - /// True if artifact appears to be linkable + /// True if artifact appears to be linkable static bool isLinkable(const ArtifactDesc& desc); - /// Try to determine the desc from just a file extension (passed without .) + /// Try to determine the desc from just a file extension (passed without .) static ArtifactDesc getDescFromExtension(const UnownedStringSlice& slice); - /// Try to determine the desc from a path + /// Try to determine the desc from a path static ArtifactDesc getDescFromPath(const UnownedStringSlice& slice); - /// Appends the default file extension for the artifact type. + /// Appends the default file extension for the artifact type. static SlangResult appendDefaultExtension(const ArtifactDesc& desc, StringBuilder& out); - /// Get the extension for CPU/Host for a kind + /// Get the extension for CPU/Host for a kind static SlangResult appendCpuExtensionForKind(Kind kind, StringBuilder& out); - /// Given a desc and a path returns the base name (stripped of prefix and extension) + /// Given a desc and a path returns the base name (stripped of prefix and extension) static String getBaseNameFromPath(const ArtifactDesc& desc, const UnownedStringSlice& path); - /// Given a desc and a name returns the base name (stripped of prefix and extension) + /// Given a desc and a name returns the base name (stripped of prefix and extension) static String getBaseNameFromName(const ArtifactDesc& desc, const UnownedStringSlice& path); - /// Get the base name of the fileRep - /// If no base name is found will return an empty slice + /// Get the base name of the fileRep + /// If no base name is found will return an empty slice static String getBaseName(const ArtifactDesc& desc, IPathArtifactRepresentation* fileRep); - /// Given a desc and a basePath returns a suitable path for a entity of specified desc - static SlangResult calcPathForDesc(const ArtifactDesc& desc, const UnownedStringSlice& basePath, StringBuilder& outPath); + /// Given a desc and a basePath returns a suitable path for a entity of specified desc + static SlangResult calcPathForDesc( + const ArtifactDesc& desc, + const UnownedStringSlice& basePath, + StringBuilder& outPath); - /// Given a desc and a baseName works out the the output file name - static SlangResult calcNameForDesc(const ArtifactDesc& desc, const UnownedStringSlice& baseName, StringBuilder& outName); + /// Given a desc and a baseName works out the the output file name + static SlangResult calcNameForDesc( + const ArtifactDesc& desc, + const UnownedStringSlice& baseName, + StringBuilder& outName); - /// Returns true if there is a defined name extension/type for this desc + /// Returns true if there is a defined name extension/type for this desc static SlangResult hasDefinedNameForDesc(const ArtifactDesc& desc); - /// Given a target returns the ArtifactDesc + /// Given a target returns the ArtifactDesc static ArtifactDesc makeDescForCompileTarget(SlangCompileTarget target); - /// Get the payload for the specified language + /// Get the payload for the specified language static ArtifactPayload getPayloadForSourceLanaguage(SlangSourceLanguage language); - /// Given a source language return a desc + /// Given a source language return a desc static ArtifactDesc makeDescForSourceLanguage(SlangSourceLanguage language); - /// Returns the closest compile target for desc. Will return - /// SLANG_TARGET_UNKNOWN if not known + /// Returns the closest compile target for desc. Will return + /// SLANG_TARGET_UNKNOWN if not known static SlangCompileTarget getCompileTargetFromDesc(const ArtifactDesc& desc); - /// Make ArtifactDesc from target + /// Make ArtifactDesc from target static bool isDescDerivedFrom(const ArtifactDesc& desc, const ArtifactDesc& from); - /// True if `to` is disassembly of `from` + /// True if `to` is disassembly of `from` static bool isDisassembly(const ArtifactDesc& from, const ArtifactDesc& to); - /// Append the desc as text to out + /// Append the desc as text to out static void appendText(const ArtifactDesc& desc, StringBuilder& out); - /// Given an artifact desc return a description as a string + /// Given an artifact desc return a description as a string static String getText(const ArtifactDesc& desc); - }; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -inline /* static */bool ArtifactDescUtil::isDescDerivedFrom(const ArtifactDesc& desc, const ArtifactDesc& from) +inline /* static */ bool ArtifactDescUtil::isDescDerivedFrom( + const ArtifactDesc& desc, + const ArtifactDesc& from) { - // TODO(JS): Currently this ignores flags in desc. That may or may not be right + // TODO(JS): Currently this ignores flags in desc. That may or may not be right // long term. - return isDerivedFrom(desc.kind, from.kind) && - isDerivedFrom(desc.payload, from.payload) && - isDerivedFrom(desc.style, from.style); + return isDerivedFrom(desc.kind, from.kind) && isDerivedFrom(desc.payload, from.payload) && + isDerivedFrom(desc.style, from.style); } } // namespace Slang diff --git a/source/compiler-core/slang-artifact-diagnostic-util.cpp b/source/compiler-core/slang-artifact-diagnostic-util.cpp index 38e5c5fd8..bf1f0474b 100644 --- a/source/compiler-core/slang-artifact-diagnostic-util.cpp +++ b/source/compiler-core/slang-artifact-diagnostic-util.cpp @@ -4,22 +4,26 @@ #include "../core/slang-char-util.h" #include "../core/slang-string-util.h" -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactDiagnosticsUtil !!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */UnownedStringSlice ArtifactDiagnosticUtil::getSeverityText(Severity severity) +/* static */ UnownedStringSlice ArtifactDiagnosticUtil::getSeverityText(Severity severity) { switch (severity) { - default: return UnownedStringSlice::fromLiteral("Unknown"); - case Severity::Info: return UnownedStringSlice::fromLiteral("Info"); - case Severity::Warning: return UnownedStringSlice::fromLiteral("Warning"); - case Severity::Error: return UnownedStringSlice::fromLiteral("Error"); + default: return UnownedStringSlice::fromLiteral("Unknown"); + case Severity::Info: return UnownedStringSlice::fromLiteral("Info"); + case Severity::Warning: return UnownedStringSlice::fromLiteral("Warning"); + case Severity::Error: return UnownedStringSlice::fromLiteral("Error"); } } -/* static */SlangResult ArtifactDiagnosticUtil::splitPathLocation(SliceAllocator& allocator, const UnownedStringSlice& pathLocation, ArtifactDiagnostic& outDiagnostic) +/* static */ SlangResult ArtifactDiagnosticUtil::splitPathLocation( + SliceAllocator& allocator, + const UnownedStringSlice& pathLocation, + ArtifactDiagnostic& outDiagnostic) { const Index lineStartIndex = pathLocation.lastIndexOf('('); if (lineStartIndex >= 0) @@ -37,8 +41,8 @@ namespace Slang { UnownedStringSlice slices[2]; const Index numSlices = StringUtil::split(locationSlice, ',', 2, slices); - // NOTE! FXC actually outputs a range of columns in the form of START-END in the column position - // We don't need to parse here, because we only care about the line number + // NOTE! FXC actually outputs a range of columns in the form of START-END in the column + // position We don't need to parse here, because we only care about the line number Int lineNumber = 0; if (numSlices > 0) @@ -57,7 +61,10 @@ namespace Slang { return SLANG_OK; } -/* static */SlangResult ArtifactDiagnosticUtil::splitColonDelimitedLine(const UnownedStringSlice& line, Int pathIndex, List& outSlices) +/* static */ SlangResult ArtifactDiagnosticUtil::splitColonDelimitedLine( + const UnownedStringSlice& line, + Int pathIndex, + List& outSlices) { StringUtil::split(line, ':', outSlices); @@ -69,7 +76,8 @@ namespace Slang { if (pathStart.getLength() == 1 && CharUtil::isAlpha(pathStart[0])) { // Splice back together - outSlices[pathIndex] = UnownedStringSlice(outSlices[pathIndex].begin(), outSlices[pathIndex + 1].end()); + outSlices[pathIndex] = + UnownedStringSlice(outSlices[pathIndex].begin(), outSlices[pathIndex + 1].end()); outSlices.removeAt(pathIndex + 1); } } @@ -77,7 +85,12 @@ namespace Slang { return SLANG_OK; } -/* static */SlangResult ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics(SliceAllocator& allocator, const UnownedStringSlice& inText, Int pathIndex, LineParser lineParser, IArtifactDiagnostics* diagnostics) +/* static */ SlangResult ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics( + SliceAllocator& allocator, + const UnownedStringSlice& inText, + Int pathIndex, + LineParser lineParser, + IArtifactDiagnostics* diagnostics) { List splitLine; @@ -106,7 +119,9 @@ namespace Slang { return SLANG_OK; } -/* static */void ArtifactDiagnosticUtil::maybeAddNote(const UnownedStringSlice& in, IArtifactDiagnostics* diagnostics) +/* static */ void ArtifactDiagnosticUtil::maybeAddNote( + const UnownedStringSlice& in, + IArtifactDiagnostics* diagnostics) { // Don't bother adding an empty line if (in.trim().getLength() == 0) diff --git a/source/compiler-core/slang-artifact-diagnostic-util.h b/source/compiler-core/slang-artifact-diagnostic-util.h index fe158ce38..2ccd13820 100644 --- a/source/compiler-core/slang-artifact-diagnostic-util.h +++ b/source/compiler-core/slang-artifact-diagnostic-util.h @@ -2,10 +2,8 @@ #ifndef SLANG_ARTIFACT_DIAGNOSTIC_UTIL_H #define SLANG_ARTIFACT_DIAGNOSTIC_UTIL_H -#include "slang-artifact.h" - #include "slang-artifact-associated.h" - +#include "slang-artifact.h" #include "slang-slice-allocator.h" namespace Slang @@ -18,16 +16,32 @@ struct ArtifactDiagnosticUtil /// Given severity return as text static UnownedStringSlice getSeverityText(Severity severity); - /// Given a path, that holds line number and potentially column number in () after path, writes result into outDiagnostic - static SlangResult splitPathLocation(SliceAllocator& allocator, const UnownedStringSlice& pathLocation, ArtifactDiagnostic& outDiagnostic); - - /// Split the line (separated by :), where a path is at pathIndex - static SlangResult splitColonDelimitedLine(const UnownedStringSlice& line, Int pathIndex, List& outSlices); - - typedef SlangResult(*LineParser)(SliceAllocator& allocator, const UnownedStringSlice& line, List& lineSlices, ArtifactDiagnostic& outDiagnostic); + /// Given a path, that holds line number and potentially column number in () after path, writes + /// result into outDiagnostic + static SlangResult splitPathLocation( + SliceAllocator& allocator, + const UnownedStringSlice& pathLocation, + ArtifactDiagnostic& outDiagnostic); + + /// Split the line (separated by :), where a path is at pathIndex + static SlangResult splitColonDelimitedLine( + const UnownedStringSlice& line, + Int pathIndex, + List& outSlices); + + typedef SlangResult (*LineParser)( + SliceAllocator& allocator, + const UnownedStringSlice& line, + List& lineSlices, + ArtifactDiagnostic& outDiagnostic); /// Given diagnostics in inText that are colon delimited, use lineParser to do per line parsing. - static SlangResult parseColonDelimitedDiagnostics(SliceAllocator& allocator, const UnownedStringSlice& inText, Int pathIndex, LineParser lineParser, IArtifactDiagnostics* diagnostics); + static SlangResult parseColonDelimitedDiagnostics( + SliceAllocator& allocator, + const UnownedStringSlice& inText, + Int pathIndex, + LineParser lineParser, + IArtifactDiagnostics* diagnostics); /// Maybe add a note static void maybeAddNote(const UnownedStringSlice& in, IArtifactDiagnostics* diagnostics); diff --git a/source/compiler-core/slang-artifact-handler-impl.cpp b/source/compiler-core/slang-artifact-handler-impl.cpp index 6fc96dc44..b19a9bd6e 100644 --- a/source/compiler-core/slang-artifact-handler-impl.cpp +++ b/source/compiler-core/slang-artifact-handler-impl.cpp @@ -1,340 +1,369 @@ // slang-artifact-handler-impl.cpp #include "slang-artifact-handler-impl.h" -#include "slang-artifact-impl.h" -#include "slang-artifact-representation-impl.h" - -#include "slang-artifact-desc-util.h" - -#include "slang-artifact-helper.h" -#include "slang-artifact-util.h" - #include "../core/slang-castable.h" - -#include "slang-slice-allocator.h" - #include "../core/slang-file-system.h" #include "../core/slang-io.h" #include "../core/slang-shared-library.h" - -#include "slang-source-map.h" - +#include "slang-artifact-desc-util.h" +#include "slang-artifact-helper.h" +#include "slang-artifact-impl.h" +#include "slang-artifact-representation-impl.h" +#include "slang-artifact-util.h" #include "slang-json-source-map-util.h" +#include "slang-slice-allocator.h" +#include "slang-source-map.h" -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DefaultArtifactHandler !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */DefaultArtifactHandler DefaultArtifactHandler::g_singleton; +/* static */ DefaultArtifactHandler DefaultArtifactHandler::g_singleton; SlangResult DefaultArtifactHandler::queryInterface(SlangUUID const& uuid, void** outObject) { - if ([[maybe_unused]] auto ptr = getInterface(uuid)) - { + if ([[maybe_unused]] auto ptr = getInterface(uuid)) + { SLANG_ASSERT(ptr == this); - addRef(); - *outObject = static_cast(this); - return SLANG_OK; - } - return SLANG_E_NO_INTERFACE; + addRef(); + *outObject = static_cast(this); + return SLANG_OK; + } + return SLANG_E_NO_INTERFACE; } void* DefaultArtifactHandler::castAs(const Guid& guid) { - if (auto ptr = getInterface(guid)) - { - return ptr; - } - return getObject(guid); + if (auto ptr = getInterface(guid)) + { + return ptr; + } + return getObject(guid); } void* DefaultArtifactHandler::getInterface(const Guid& uuid) { - if (uuid == ISlangUnknown::getTypeGuid() || - uuid == ICastable::getTypeGuid() || - uuid == IArtifactHandler::getTypeGuid()) - { - return static_cast(this); - } - - return nullptr; + if (uuid == ISlangUnknown::getTypeGuid() || uuid == ICastable::getTypeGuid() || + uuid == IArtifactHandler::getTypeGuid()) + { + return static_cast(this); + } + + return nullptr; } void* DefaultArtifactHandler::getObject(const Guid& uuid) { - SLANG_UNUSED(uuid); - return nullptr; + SLANG_UNUSED(uuid); + return nullptr; } -SlangResult DefaultArtifactHandler::_addRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangUnknown* rep, ICastable** outCastable) +SlangResult DefaultArtifactHandler::_addRepresentation( + IArtifact* artifact, + ArtifactKeep keep, + ISlangUnknown* rep, + ICastable** outCastable) { - SLANG_ASSERT(rep); - - // See if it implements ICastable - { - ComPtr castable; - if (SLANG_SUCCEEDED(rep->queryInterface(SLANG_IID_PPV_ARGS(castable.writeRef()))) && castable) - { - return _addRepresentation(artifact, keep, castable, outCastable); - } - } - - // We have to wrap - ComPtr adapter(new UnknownCastableAdapter(rep)); - return _addRepresentation(artifact, keep, adapter, outCastable); + SLANG_ASSERT(rep); + + // See if it implements ICastable + { + ComPtr castable; + if (SLANG_SUCCEEDED(rep->queryInterface(SLANG_IID_PPV_ARGS(castable.writeRef()))) && + castable) + { + return _addRepresentation(artifact, keep, castable, outCastable); + } + } + + // We have to wrap + ComPtr adapter(new UnknownCastableAdapter(rep)); + return _addRepresentation(artifact, keep, adapter, outCastable); } -SlangResult DefaultArtifactHandler::_addRepresentation(IArtifact* artifact, ArtifactKeep keep, ICastable* castable, ICastable** outCastable) +SlangResult DefaultArtifactHandler::_addRepresentation( + IArtifact* artifact, + ArtifactKeep keep, + ICastable* castable, + ICastable** outCastable) { - SLANG_ASSERT(castable); + SLANG_ASSERT(castable); - if (canKeep(keep)) - { - artifact->addRepresentation(castable); - } + if (canKeep(keep)) + { + artifact->addRepresentation(castable); + } - castable->addRef(); - *outCastable = castable; - return SLANG_OK; + castable->addRef(); + *outCastable = castable; + return SLANG_OK; } SlangResult DefaultArtifactHandler::expandChildren(IArtifact* container) { - // First check if it has already been expanded - SlangResult res = container->getExpandChildrenResult(); - if (res != SLANG_E_UNINITIALIZED) - { - // It's already expanded - return res; - } - - // For the generic container type, we just expand as empty - const auto desc = container->getDesc(); + // First check if it has already been expanded + SlangResult res = container->getExpandChildrenResult(); + if (res != SLANG_E_UNINITIALIZED) + { + // It's already expanded + return res; + } + + // For the generic container type, we just expand as empty + const auto desc = container->getDesc(); if (desc.kind == ArtifactKind::Container) { // If it's just a generic container, we can assume it's expanded, and be done return SLANG_OK; } - if (isDerivedFrom(desc.kind, ArtifactKind::Container)) - { + if (isDerivedFrom(desc.kind, ArtifactKind::Container)) + { // TODO(JS): // Proper implementation should (for example) be able to expand a Zip file etc. // For now we just set that there are no children, and be done - container->setChildren(nullptr, 0); - return SLANG_E_NOT_IMPLEMENTED; - } + container->setChildren(nullptr, 0); + return SLANG_E_NOT_IMPLEMENTED; + } // We can't expand non container like types, so we just make sure it's empty container->setChildren(nullptr, 0); - return SLANG_OK; + return SLANG_OK; } -static SlangResult _loadSourceMap(IArtifact* artifact, ArtifactKeep intermediateKeep, SourceMap& outSourceMap) +static SlangResult _loadSourceMap( + IArtifact* artifact, + ArtifactKeep intermediateKeep, + SourceMap& outSourceMap) { - const auto desc = artifact->getDesc(); - if (isDerivedFrom(desc.kind, ArtifactKind::Json) && - isDerivedFrom(desc.payload, ArtifactPayload::SourceMap)) - { - ComPtr blob; - SLANG_RETURN_ON_FAIL(artifact->loadBlob(intermediateKeep, blob.writeRef())); - - SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::read(blob, outSourceMap)); - return SLANG_OK; - } - - return SLANG_FAIL; + const auto desc = artifact->getDesc(); + if (isDerivedFrom(desc.kind, ArtifactKind::Json) && + isDerivedFrom(desc.payload, ArtifactPayload::SourceMap)) + { + ComPtr blob; + SLANG_RETURN_ON_FAIL(artifact->loadBlob(intermediateKeep, blob.writeRef())); + + SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::read(blob, outSourceMap)); + return SLANG_OK; + } + + return SLANG_FAIL; } -SlangResult DefaultArtifactHandler::getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable) +SlangResult DefaultArtifactHandler::getOrCreateRepresentation( + IArtifact* artifact, + const Guid& guid, + ArtifactKeep keep, + ICastable** outCastable) { - const auto reps = artifact->getRepresentations(); - - // See if we already have a rep of this type - for (ICastable* rep : reps) - { - if (rep->castAs(guid)) - { - rep->addRef(); - *outCastable = rep; - return SLANG_OK; - } - } - - // We can ask each representation if they can do the conversion to the type, if they can we just use that - for (ICastable* castable : reps) - { - if (auto rep = as(castable)) - { - ComPtr created; - if (SLANG_SUCCEEDED(rep->createRepresentation(guid, created.writeRef()))) - { - SLANG_ASSERT(created); - // Add the rep - return _addRepresentation(artifact, keep, created, outCastable); - } - } - } - - // Special cases - if (guid == SourceMap::getTypeGuid()) - { - // Blob -> SourceMap - ComPtr> sourceMap(new BoxValue); - SLANG_RETURN_ON_FAIL(_loadSourceMap(artifact, getIntermediateKeep(keep), sourceMap->get())); - return _addRepresentation(artifact, keep, sourceMap, outCastable); - } - else if (guid == ISlangSharedLibrary::getTypeGuid()) - { - ComPtr sharedLib; - SLANG_RETURN_ON_FAIL(_loadSharedLibrary(artifact, sharedLib.writeRef())); - return _addRepresentation(artifact, keep, sharedLib, outCastable); - } - else if (guid == IOSFileArtifactRepresentation::getTypeGuid()) - { - ComPtr fileRep; - SLANG_RETURN_ON_FAIL(_createOSFile(artifact, getIntermediateKeep(keep), fileRep.writeRef())); - return _addRepresentation(artifact, keep, fileRep, outCastable); - } - - // Handle known conversion to blobs - if (guid == ISlangBlob::getTypeGuid()) - { - if (auto sourceMap = findRepresentation(artifact)) - { - // SourceMap -> Blob - ComPtr blob; - SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::write(*sourceMap, blob)); - // Add the rep - return _addRepresentation(artifact, keep, blob, outCastable); - } - } - - return SLANG_E_NOT_AVAILABLE; + const auto reps = artifact->getRepresentations(); + + // See if we already have a rep of this type + for (ICastable* rep : reps) + { + if (rep->castAs(guid)) + { + rep->addRef(); + *outCastable = rep; + return SLANG_OK; + } + } + + // We can ask each representation if they can do the conversion to the type, if they can we just + // use that + for (ICastable* castable : reps) + { + if (auto rep = as(castable)) + { + ComPtr created; + if (SLANG_SUCCEEDED(rep->createRepresentation(guid, created.writeRef()))) + { + SLANG_ASSERT(created); + // Add the rep + return _addRepresentation(artifact, keep, created, outCastable); + } + } + } + + // Special cases + if (guid == SourceMap::getTypeGuid()) + { + // Blob -> SourceMap + ComPtr> sourceMap(new BoxValue); + SLANG_RETURN_ON_FAIL(_loadSourceMap(artifact, getIntermediateKeep(keep), sourceMap->get())); + return _addRepresentation(artifact, keep, sourceMap, outCastable); + } + else if (guid == ISlangSharedLibrary::getTypeGuid()) + { + ComPtr sharedLib; + SLANG_RETURN_ON_FAIL(_loadSharedLibrary(artifact, sharedLib.writeRef())); + return _addRepresentation(artifact, keep, sharedLib, outCastable); + } + else if (guid == IOSFileArtifactRepresentation::getTypeGuid()) + { + ComPtr fileRep; + SLANG_RETURN_ON_FAIL( + _createOSFile(artifact, getIntermediateKeep(keep), fileRep.writeRef())); + return _addRepresentation(artifact, keep, fileRep, outCastable); + } + + // Handle known conversion to blobs + if (guid == ISlangBlob::getTypeGuid()) + { + if (auto sourceMap = findRepresentation(artifact)) + { + // SourceMap -> Blob + ComPtr blob; + SLANG_RETURN_ON_FAIL(JSONSourceMapUtil::write(*sourceMap, blob)); + // Add the rep + return _addRepresentation(artifact, keep, blob, outCastable); + } + } + + return SLANG_E_NOT_AVAILABLE; } -SlangResult DefaultArtifactHandler::_createOSFile(IArtifact* artifact, ArtifactKeep keep, IOSFileArtifactRepresentation** outFileRep) +SlangResult DefaultArtifactHandler::_createOSFile( + IArtifact* artifact, + ArtifactKeep keep, + IOSFileArtifactRepresentation** outFileRep) { - // Look if we have an IExtFile representation, as we might already have a OS file associated with that - if (auto extRep = findRepresentation(artifact)) - { - auto system = extRep->getFileSystem(); - - String path; - switch (system->getOSPathKind()) - { - case OSPathKind::Direct: - { - path = UnownedStringSlice(extRep->getPath()); - break; - } - case OSPathKind::OperatingSystem: - { - ComPtr osPathBlob; - if (SLANG_SUCCEEDED(system->getPath(PathKind::OperatingSystem, extRep->getPath(), osPathBlob.writeRef()))) - { - path = StringUtil::getString(osPathBlob); - } - break; - } - default: break; - } - - if (path.getLength()) - { - auto fileRep = OSFileArtifactRepresentation::create(IOSFileArtifactRepresentation::Kind::Reference, path.getUnownedSlice() , nullptr); - // As a sanity check make sure it exists! - if (fileRep->exists()) - { - *outFileRep = fileRep.detach(); - return SLANG_OK; - } - } - } - - // Okay looks like we will need to generate a temporary file - auto helper = DefaultArtifactHelper::getSingleton(); - - // If we are going to access as a file we need to be able to write it, and to do that we need a blob - ComPtr blob; - SLANG_RETURN_ON_FAIL(artifact->loadBlob(getIntermediateKeep(keep), blob.writeRef())); - - // Find some name associated - auto name = ArtifactUtil::findName(artifact); - if (name.getLength() == 0) - { - name = toSlice("unknown"); - } - - // Okay we need to store as a temporary. Get a lock file. - ComPtr lockFile; - SLANG_RETURN_ON_FAIL(helper->createLockFile(asCharSlice(name), lockFile.writeRef())); - - // Now we need the appropriate name for this item - ComPtr pathBlob; - SLANG_RETURN_ON_FAIL(helper->calcArtifactPath(artifact, lockFile->getPath(), pathBlob.writeRef())); - - const auto path = StringUtil::getSlice(pathBlob); - - // Write the contents - SLANG_RETURN_ON_FAIL(File::writeAllBytes(path, blob->getBufferPointer(), blob->getBufferSize())); - if(artifact->getDesc().kind == ArtifactKind::Executable) + // Look if we have an IExtFile representation, as we might already have a OS file associated + // with that + if (auto extRep = findRepresentation(artifact)) + { + auto system = extRep->getFileSystem(); + + String path; + switch (system->getOSPathKind()) + { + case OSPathKind::Direct: + { + path = UnownedStringSlice(extRep->getPath()); + break; + } + case OSPathKind::OperatingSystem: + { + ComPtr osPathBlob; + if (SLANG_SUCCEEDED(system->getPath( + PathKind::OperatingSystem, + extRep->getPath(), + osPathBlob.writeRef()))) + { + path = StringUtil::getString(osPathBlob); + } + break; + } + default: break; + } + + if (path.getLength()) + { + auto fileRep = OSFileArtifactRepresentation::create( + IOSFileArtifactRepresentation::Kind::Reference, + path.getUnownedSlice(), + nullptr); + // As a sanity check make sure it exists! + if (fileRep->exists()) + { + *outFileRep = fileRep.detach(); + return SLANG_OK; + } + } + } + + // Okay looks like we will need to generate a temporary file + auto helper = DefaultArtifactHelper::getSingleton(); + + // If we are going to access as a file we need to be able to write it, and to do that we need a + // blob + ComPtr blob; + SLANG_RETURN_ON_FAIL(artifact->loadBlob(getIntermediateKeep(keep), blob.writeRef())); + + // Find some name associated + auto name = ArtifactUtil::findName(artifact); + if (name.getLength() == 0) + { + name = toSlice("unknown"); + } + + // Okay we need to store as a temporary. Get a lock file. + ComPtr lockFile; + SLANG_RETURN_ON_FAIL(helper->createLockFile(asCharSlice(name), lockFile.writeRef())); + + // Now we need the appropriate name for this item + ComPtr pathBlob; + SLANG_RETURN_ON_FAIL( + helper->calcArtifactPath(artifact, lockFile->getPath(), pathBlob.writeRef())); + + const auto path = StringUtil::getSlice(pathBlob); + + // Write the contents + SLANG_RETURN_ON_FAIL( + File::writeAllBytes(path, blob->getBufferPointer(), blob->getBufferSize())); + if (artifact->getDesc().kind == ArtifactKind::Executable) { SLANG_RETURN_ON_FAIL(File::makeExecutable(path)); } - ComPtr fileRep; - - // TODO(JS): This path comparison is perhaps not perfect, in that it assumes the path is not changed - // in any way. For example an impl of calcArtifactPath that changed slashes or used a canonical path - // might mean the lock file and the rep have the same path. - // As it stands calcArtifactPath impl doesn't do that, but that is perhaps somewhatfragile - - // If the paths are identical, we can just use the lock file for the rep - if (UnownedStringSlice(lockFile->getPath()) == path) - { - fileRep.swap(lockFile); - } - else - { - // Create a new rep that references the lock file - fileRep = new OSFileArtifactRepresentation(IOSFileArtifactRepresentation::Kind::Owned, path, lockFile); - } - - // Return the file - *outFileRep = fileRep.detach(); - return SLANG_OK; + ComPtr fileRep; + + // TODO(JS): This path comparison is perhaps not perfect, in that it assumes the path is not + // changed in any way. For example an impl of calcArtifactPath that changed slashes or used a + // canonical path might mean the lock file and the rep have the same path. As it stands + // calcArtifactPath impl doesn't do that, but that is perhaps somewhatfragile + + // If the paths are identical, we can just use the lock file for the rep + if (UnownedStringSlice(lockFile->getPath()) == path) + { + fileRep.swap(lockFile); + } + else + { + // Create a new rep that references the lock file + fileRep = new OSFileArtifactRepresentation( + IOSFileArtifactRepresentation::Kind::Owned, + path, + lockFile); + } + + // Return the file + *outFileRep = fileRep.detach(); + return SLANG_OK; } -SlangResult DefaultArtifactHandler::_loadSharedLibrary(IArtifact* artifact, ISlangSharedLibrary** outSharedLibrary) +SlangResult DefaultArtifactHandler::_loadSharedLibrary( + IArtifact* artifact, + ISlangSharedLibrary** outSharedLibrary) { - // If it is 'shared library' for a CPU like thing, we can try and load it - const auto desc = artifact->getDesc(); - if ((isDerivedFrom(desc.kind, ArtifactKind::HostCallable) || - isDerivedFrom(desc.kind, ArtifactKind::SharedLibrary)) && - isDerivedFrom(desc.payload, ArtifactPayload::CPULike)) - { - // Get as a file represenation on the OS file system - ComPtr fileRep; - - // We want to keep the file representation, otherwise every request, could produce a new file - // and that seems like a bad idea. - SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef())); - - // Try loading the shared library - SharedLibrary::Handle handle; - if (SLANG_FAILED(SharedLibrary::loadWithPlatformPath(fileRep->getPath(), handle))) - { - return SLANG_FAIL; - } - - // Output - *outSharedLibrary = ScopeSharedLibrary::create(handle, fileRep).detach(); - return SLANG_OK; - } - - return SLANG_FAIL; + // If it is 'shared library' for a CPU like thing, we can try and load it + const auto desc = artifact->getDesc(); + if ((isDerivedFrom(desc.kind, ArtifactKind::HostCallable) || + isDerivedFrom(desc.kind, ArtifactKind::SharedLibrary)) && + isDerivedFrom(desc.payload, ArtifactPayload::CPULike)) + { + // Get as a file represenation on the OS file system + ComPtr fileRep; + + // We want to keep the file representation, otherwise every request, could produce a new + // file and that seems like a bad idea. + SLANG_RETURN_ON_FAIL(artifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef())); + + // Try loading the shared library + SharedLibrary::Handle handle; + if (SLANG_FAILED(SharedLibrary::loadWithPlatformPath(fileRep->getPath(), handle))) + { + return SLANG_FAIL; + } + + // Output + *outSharedLibrary = ScopeSharedLibrary::create(handle, fileRep).detach(); + return SLANG_OK; + } + + return SLANG_FAIL; } } // namespace Slang diff --git a/source/compiler-core/slang-artifact-handler-impl.h b/source/compiler-core/slang-artifact-handler-impl.h index c1cd25980..675dcd5f2 100644 --- a/source/compiler-core/slang-artifact-handler-impl.h +++ b/source/compiler-core/slang-artifact-handler-impl.h @@ -2,10 +2,9 @@ #ifndef SLANG_ARTIFACT_HANDLER_IMPL_H #define SLANG_ARTIFACT_HANDLER_IMPL_H -#include "slang-artifact.h" -#include "slang-artifact-representation.h" - #include "../core/slang-com-object.h" +#include "slang-artifact-representation.h" +#include "slang-artifact.h" namespace Slang { @@ -13,30 +12,46 @@ namespace Slang class DefaultArtifactHandler : public ComBaseObject, public IArtifactHandler { public: - SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } - SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } - SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE; - - // ICastable - SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; - - // IArtifactHandler - SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren(IArtifact* container) SLANG_OVERRIDE; - SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable) SLANG_OVERRIDE; - - static IArtifactHandler* getSingleton() { return &g_singleton; } -protected: + SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) + SLANG_OVERRIDE; - SlangResult _loadSharedLibrary(IArtifact* artifact, ISlangSharedLibrary** outSharedLibrary); - SlangResult _createOSFile(IArtifact* artifact, ArtifactKeep intermediateKeep, IOSFileArtifactRepresentation** outFileRep); + // ICastable + SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; - void* getInterface(const Guid& uuid); - void* getObject(const Guid& uuid); + // IArtifactHandler + SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren(IArtifact* container) SLANG_OVERRIDE; + SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation( + IArtifact* artifact, + const Guid& guid, + ArtifactKeep keep, + ICastable** outCastable) SLANG_OVERRIDE; - SlangResult _addRepresentation(IArtifact* artifact, ArtifactKeep keep, ISlangUnknown* rep, ICastable** outCastable); - SlangResult _addRepresentation(IArtifact* artifact, ArtifactKeep keep, ICastable* castable, ICastable** outCastable); - - static DefaultArtifactHandler g_singleton; + static IArtifactHandler* getSingleton() { return &g_singleton; } + +protected: + SlangResult _loadSharedLibrary(IArtifact* artifact, ISlangSharedLibrary** outSharedLibrary); + SlangResult _createOSFile( + IArtifact* artifact, + ArtifactKeep intermediateKeep, + IOSFileArtifactRepresentation** outFileRep); + + void* getInterface(const Guid& uuid); + void* getObject(const Guid& uuid); + + SlangResult _addRepresentation( + IArtifact* artifact, + ArtifactKeep keep, + ISlangUnknown* rep, + ICastable** outCastable); + SlangResult _addRepresentation( + IArtifact* artifact, + ArtifactKeep keep, + ICastable* castable, + ICastable** outCastable); + + static DefaultArtifactHandler g_singleton; }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-helper.cpp b/source/compiler-core/slang-artifact-helper.cpp index 7f1bf1ea2..dc4d6638d 100644 --- a/source/compiler-core/slang-artifact-helper.cpp +++ b/source/compiler-core/slang-artifact-helper.cpp @@ -1,141 +1,191 @@ // slang-artifact-helper.cpp #include "slang-artifact-helper.h" -#include "slang-artifact-impl.h" -#include "slang-artifact-representation-impl.h" - -#include "slang-artifact-desc-util.h" -#include "slang-artifact-util.h" - #include "../compiler-core/slang-slice-allocator.h" - #include "../core/slang-castable.h" - #include "../core/slang-file-system.h" #include "../core/slang-io.h" #include "../core/slang-shared-library.h" +#include "slang-artifact-desc-util.h" +#include "slang-artifact-impl.h" +#include "slang-artifact-representation-impl.h" +#include "slang-artifact-util.h" -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!! DefaultArtifactHelper !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */DefaultArtifactHelper DefaultArtifactHelper::g_singleton; +/* static */ DefaultArtifactHelper DefaultArtifactHelper::g_singleton; SlangResult DefaultArtifactHelper::queryInterface(SlangUUID const& uuid, void** outObject) { - if (auto intf = getInterface(uuid)) - { - *outObject = intf; - return SLANG_OK; - } - return SLANG_E_NO_INTERFACE; + if (auto intf = getInterface(uuid)) + { + *outObject = intf; + return SLANG_OK; + } + return SLANG_E_NO_INTERFACE; } void* DefaultArtifactHelper::castAs(const Guid& guid) { - if (auto ptr = getInterface(guid)) - { - return ptr; - } - return getObject(guid); + if (auto ptr = getInterface(guid)) + { + return ptr; + } + return getObject(guid); } void* DefaultArtifactHelper::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == IArtifactHelper::getTypeGuid()) - { - return static_cast(this); - } - return nullptr; + if (guid == ISlangUnknown::getTypeGuid() || guid == IArtifactHelper::getTypeGuid()) + { + return static_cast(this); + } + return nullptr; } void* DefaultArtifactHelper::getObject(const Guid& guid) { - SLANG_UNUSED(guid); - return nullptr; + SLANG_UNUSED(guid); + return nullptr; } -SlangResult DefaultArtifactHelper::createArtifact(const ArtifactDesc& desc, const char* inName, IArtifact** outArtifact) +SlangResult DefaultArtifactHelper::createArtifact( + const ArtifactDesc& desc, + const char* inName, + IArtifact** outArtifact) { - *outArtifact = inName ? - Artifact::create(desc, UnownedStringSlice(inName)).detach() : - Artifact::create(desc).detach(); + *outArtifact = inName ? Artifact::create(desc, UnownedStringSlice(inName)).detach() + : Artifact::create(desc).detach(); - return SLANG_OK; + return SLANG_OK; } -ArtifactKind DefaultArtifactHelper::getKindParent(ArtifactKind kind) { return getParent(kind); } -UnownedStringSlice DefaultArtifactHelper::getKindName(ArtifactKind kind) { return getName(kind); } -bool DefaultArtifactHelper::isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) { return isDerivedFrom(kind, base); } +ArtifactKind DefaultArtifactHelper::getKindParent(ArtifactKind kind) +{ + return getParent(kind); +} +UnownedStringSlice DefaultArtifactHelper::getKindName(ArtifactKind kind) +{ + return getName(kind); +} +bool DefaultArtifactHelper::isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) +{ + return isDerivedFrom(kind, base); +} -ArtifactPayload DefaultArtifactHelper::getPayloadParent(ArtifactPayload payload) { return getParent(payload); } -UnownedStringSlice DefaultArtifactHelper::getPayloadName(ArtifactPayload payload) { return getName(payload); } -bool DefaultArtifactHelper::isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) { return isDerivedFrom(payload, base); } +ArtifactPayload DefaultArtifactHelper::getPayloadParent(ArtifactPayload payload) +{ + return getParent(payload); +} +UnownedStringSlice DefaultArtifactHelper::getPayloadName(ArtifactPayload payload) +{ + return getName(payload); +} +bool DefaultArtifactHelper::isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) +{ + return isDerivedFrom(payload, base); +} -ArtifactStyle DefaultArtifactHelper::getStyleParent(ArtifactStyle style) { return getParent(style); } -UnownedStringSlice DefaultArtifactHelper::getStyleName(ArtifactStyle style) { return getName(style); } -bool DefaultArtifactHelper::isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) { return isDerivedFrom(style, base); } +ArtifactStyle DefaultArtifactHelper::getStyleParent(ArtifactStyle style) +{ + return getParent(style); +} +UnownedStringSlice DefaultArtifactHelper::getStyleName(ArtifactStyle style) +{ + return getName(style); +} +bool DefaultArtifactHelper::isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) +{ + return isDerivedFrom(style, base); +} -SlangResult DefaultArtifactHelper::createLockFile(const CharSlice& inNameBase, IOSFileArtifactRepresentation** outLockFile) +SlangResult DefaultArtifactHelper::createLockFile( + const CharSlice& inNameBase, + IOSFileArtifactRepresentation** outLockFile) { - const UnownedStringSlice nameBase = inNameBase.count ? asStringSlice(inNameBase) : UnownedStringSlice("unknown"); - String lockPath; - SLANG_RETURN_ON_FAIL(File::generateTemporary(nameBase, lockPath)); - *outLockFile = OSFileArtifactRepresentation::create(IOSFileArtifactRepresentation::Kind::Lock, lockPath.getUnownedSlice(), nullptr).detach(); - return SLANG_OK; + const UnownedStringSlice nameBase = + inNameBase.count ? asStringSlice(inNameBase) : UnownedStringSlice("unknown"); + String lockPath; + SLANG_RETURN_ON_FAIL(File::generateTemporary(nameBase, lockPath)); + *outLockFile = OSFileArtifactRepresentation::create( + IOSFileArtifactRepresentation::Kind::Lock, + lockPath.getUnownedSlice(), + nullptr) + .detach(); + return SLANG_OK; } -SlangResult DefaultArtifactHelper::calcArtifactDescPath(const ArtifactDesc& desc, const char* inBasePath, ISlangBlob** outPath) +SlangResult DefaultArtifactHelper::calcArtifactDescPath( + const ArtifactDesc& desc, + const char* inBasePath, + ISlangBlob** outPath) { - UnownedStringSlice basePath(inBasePath); - StringBuilder path; - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, basePath, path)); - *outPath = StringBlob::moveCreate(path).detach(); - return SLANG_OK; + UnownedStringSlice basePath(inBasePath); + StringBuilder path; + SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, basePath, path)); + *outPath = StringBlob::moveCreate(path).detach(); + return SLANG_OK; } -SlangResult DefaultArtifactHelper::calcArtifactPath(IArtifact* artifact, const char* inBasePath, ISlangBlob** outPath) +SlangResult DefaultArtifactHelper::calcArtifactPath( + IArtifact* artifact, + const char* inBasePath, + ISlangBlob** outPath) { - UnownedStringSlice basePath(inBasePath); - StringBuilder path; - SLANG_RETURN_ON_FAIL(ArtifactUtil::calcPath(artifact, basePath, path)); - *outPath = StringBlob::moveCreate(path).detach(); - return SLANG_OK; + UnownedStringSlice basePath(inBasePath); + StringBuilder path; + SLANG_RETURN_ON_FAIL(ArtifactUtil::calcPath(artifact, basePath, path)); + *outPath = StringBlob::moveCreate(path).detach(); + return SLANG_OK; } ArtifactDesc DefaultArtifactHelper::makeDescForCompileTarget(SlangCompileTarget target) { - return ArtifactDescUtil::makeDescForCompileTarget(target); + return ArtifactDescUtil::makeDescForCompileTarget(target); } void DefaultArtifactHelper::getCastable(ISlangUnknown* unk, ICastable** outCastable) { - *outCastable = CastableUtil::getCastable(unk).detach(); + *outCastable = CastableUtil::getCastable(unk).detach(); } SlangResult DefaultArtifactHelper::createOSFileArtifactRepresentation( - IOSFileArtifactRepresentation::Kind kind, const CharSlice& path, IOSFileArtifactRepresentation* lockFile, IOSFileArtifactRepresentation** outRep) + IOSFileArtifactRepresentation::Kind kind, + const CharSlice& path, + IOSFileArtifactRepresentation* lockFile, + IOSFileArtifactRepresentation** outRep) { - *outRep = OSFileArtifactRepresentation::create(kind, asStringSlice(path), lockFile).detach(); - return SLANG_OK; + *outRep = OSFileArtifactRepresentation::create(kind, asStringSlice(path), lockFile).detach(); + return SLANG_OK; } -SlangResult DefaultArtifactHelper::createExtFileArtifactRepresentation(const CharSlice& path, ISlangFileSystemExt* system, IExtFileArtifactRepresentation** outRep) +SlangResult DefaultArtifactHelper::createExtFileArtifactRepresentation( + const CharSlice& path, + ISlangFileSystemExt* system, + IExtFileArtifactRepresentation** outRep) { - *outRep = ExtFileArtifactRepresentation::create(asStringSlice(path), system).detach(); - return SLANG_OK; + *outRep = ExtFileArtifactRepresentation::create(asStringSlice(path), system).detach(); + return SLANG_OK; } -SlangResult DefaultArtifactHelper::createOSFileArtifact(const ArtifactDesc& desc, const CharSlice& path, IArtifact** outArtifact) +SlangResult DefaultArtifactHelper::createOSFileArtifact( + const ArtifactDesc& desc, + const CharSlice& path, + IArtifact** outArtifact) { - auto artifact = Artifact::create(desc); + auto artifact = Artifact::create(desc); + + auto fileRep = new OSFileArtifactRepresentation( + IOSFileArtifactRepresentation::Kind::Reference, + asStringSlice(path), + nullptr); + artifact->addRepresentation(fileRep); - auto fileRep = new OSFileArtifactRepresentation(IOSFileArtifactRepresentation::Kind::Reference, asStringSlice(path), nullptr); - artifact->addRepresentation(fileRep); - - *outArtifact = artifact.detach(); - return SLANG_OK; + *outArtifact = artifact.detach(); + return SLANG_OK; } } // namespace Slang diff --git a/source/compiler-core/slang-artifact-helper.h b/source/compiler-core/slang-artifact-helper.h index a0d4d6b75..530a36de9 100644 --- a/source/compiler-core/slang-artifact-helper.h +++ b/source/compiler-core/slang-artifact-helper.h @@ -2,116 +2,165 @@ #ifndef SLANG_ARTIFACT_HELPER_H #define SLANG_ARTIFACT_HELPER_H -#include "slang-artifact.h" -#include "slang-artifact-representation.h" - #include "../core/slang-com-object.h" +#include "slang-artifact-representation.h" +#include "slang-artifact.h" namespace Slang { class IArtifactHelper : public ICastable { - SLANG_COM_INTERFACE(0x882b25d7, 0xe300, 0x4b20, { 0xbe, 0xb, 0x26, 0xd2, 0x52, 0x3e, 0x70, 0x20 }) - - /// Create an artifact - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifact(const ArtifactDesc& desc, const char* name, IArtifact** outArtifact) = 0; - - /// Get the parent to a kind - virtual SLANG_NO_THROW ArtifactKind SLANG_MCALL getKindParent(ArtifactKind kind) = 0; - /// Get the name of a kind - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getKindName(ArtifactKind kind) = 0; - /// Returns true if kind is derived from base - virtual SLANG_NO_THROW bool SLANG_MCALL isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) = 0; - - /// Get the parent payload for payload - virtual SLANG_NO_THROW ArtifactPayload SLANG_MCALL getPayloadParent(ArtifactPayload payload) = 0; - /// Get the payload name text - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getPayloadName(ArtifactPayload payload) = 0; - /// Returns true if payload is derived from base - virtual SLANG_NO_THROW bool SLANG_MCALL isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) = 0; - - /// Get the parent type of a style - virtual SLANG_NO_THROW ArtifactStyle SLANG_MCALL getStyleParent(ArtifactStyle style) = 0; - /// Get text name for a style - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) = 0; - /// Returns true if style is derived from base - virtual SLANG_NO_THROW bool SLANG_MCALL isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) = 0; - - /// Create a lock file, the path of which can be used to generate other temporary files - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const CharSlice& nameBase, IOSFileArtifactRepresentation** outLockFile) = 0; - - /// Given a desc and a basePath returns a suitable name - virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactDescPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) = 0; - - /// Given an artifact and a basePath returns a suitable name - virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactPath(IArtifact* , const char* basePath, ISlangBlob** outPath) = 0; - - /// Given a compile target return the equivalent desc - virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL makeDescForCompileTarget(SlangCompileTarget target) = 0; - - /// Given an interface returns as a castable interface. This might just cast unk into ICastable, or wrap it such that it uses the castable interface - virtual SLANG_NO_THROW void SLANG_MCALL getCastable(ISlangUnknown* unk, ICastable** outCastable) = 0; - - /// Create a file rep - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifactRepresentation( - IOSFileArtifactRepresentation::Kind kind, const CharSlice& path, IOSFileArtifactRepresentation* lockFile, IOSFileArtifactRepresentation** outRep) = 0; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createExtFileArtifactRepresentation(const CharSlice& path, ISlangFileSystemExt* system, IExtFileArtifactRepresentation** outRep) = 0; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifact(const ArtifactDesc& desc, const CharSlice& slice, IArtifact** outArtifact) = 0; + SLANG_COM_INTERFACE(0x882b25d7, 0xe300, 0x4b20, {0xbe, 0xb, 0x26, 0xd2, 0x52, 0x3e, 0x70, 0x20}) + + /// Create an artifact + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + createArtifact(const ArtifactDesc& desc, const char* name, IArtifact** outArtifact) = 0; + + /// Get the parent to a kind + virtual SLANG_NO_THROW ArtifactKind SLANG_MCALL getKindParent(ArtifactKind kind) = 0; + /// Get the name of a kind + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getKindName(ArtifactKind kind) = 0; + /// Returns true if kind is derived from base + virtual SLANG_NO_THROW bool SLANG_MCALL + isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) = 0; + + /// Get the parent payload for payload + virtual SLANG_NO_THROW ArtifactPayload SLANG_MCALL + getPayloadParent(ArtifactPayload payload) = 0; + /// Get the payload name text + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL + getPayloadName(ArtifactPayload payload) = 0; + /// Returns true if payload is derived from base + virtual SLANG_NO_THROW bool SLANG_MCALL + isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) = 0; + + /// Get the parent type of a style + virtual SLANG_NO_THROW ArtifactStyle SLANG_MCALL getStyleParent(ArtifactStyle style) = 0; + /// Get text name for a style + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) = 0; + /// Returns true if style is derived from base + virtual SLANG_NO_THROW bool SLANG_MCALL + isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) = 0; + + /// Create a lock file, the path of which can be used to generate other temporary files + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + createLockFile(const CharSlice& nameBase, IOSFileArtifactRepresentation** outLockFile) = 0; + + /// Given a desc and a basePath returns a suitable name + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + calcArtifactDescPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) = 0; + + /// Given an artifact and a basePath returns a suitable name + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + calcArtifactPath(IArtifact*, const char* basePath, ISlangBlob** outPath) = 0; + + /// Given a compile target return the equivalent desc + virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL + makeDescForCompileTarget(SlangCompileTarget target) = 0; + + /// Given an interface returns as a castable interface. This might just cast unk into ICastable, + /// or wrap it such that it uses the castable interface + virtual SLANG_NO_THROW void SLANG_MCALL + getCastable(ISlangUnknown* unk, ICastable** outCastable) = 0; + + /// Create a file rep + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifactRepresentation( + IOSFileArtifactRepresentation::Kind kind, + const CharSlice& path, + IOSFileArtifactRepresentation* lockFile, + IOSFileArtifactRepresentation** outRep) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createExtFileArtifactRepresentation( + const CharSlice& path, + ISlangFileSystemExt* system, + IExtFileArtifactRepresentation** outRep) = 0; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifact( + const ArtifactDesc& desc, + const CharSlice& slice, + IArtifact** outArtifact) = 0; }; class DefaultArtifactHelper : public IArtifactHelper { public: - // ISlangUnknown - SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } - SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } - SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE; - - // ICastable - SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; - - // IArtifactHelper - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifact(const ArtifactDesc& desc, const char* name, IArtifact** outArtifact) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW ArtifactKind SLANG_MCALL getKindParent(ArtifactKind kind) SLANG_OVERRIDE; - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getKindName(ArtifactKind kind) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW ArtifactPayload SLANG_MCALL getPayloadParent(ArtifactPayload payload) SLANG_OVERRIDE; - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getPayloadName(ArtifactPayload payload) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW ArtifactStyle SLANG_MCALL getStyleParent(ArtifactStyle style) SLANG_OVERRIDE; - virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile(const CharSlice& nameBase, IOSFileArtifactRepresentation** outLockFile) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactDescPath(const ArtifactDesc& desc, const char* basePath, ISlangBlob** outPath) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactPath(IArtifact*, const char* basePath, ISlangBlob** outPath) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL makeDescForCompileTarget(SlangCompileTarget target) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW void SLANG_MCALL getCastable(ISlangUnknown* unk, ICastable** outCastable) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifactRepresentation( - IOSFileArtifactRepresentation::Kind kind, const CharSlice& path, IOSFileArtifactRepresentation* lockFile, IOSFileArtifactRepresentation** outRep) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createExtFileArtifactRepresentation(const CharSlice& path, ISlangFileSystemExt* system, IExtFileArtifactRepresentation** outRep) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifact(const ArtifactDesc& desc, const CharSlice& slice, IArtifact** outArtifact) SLANG_OVERRIDE; - - static IArtifactHelper* getSingleton() { return &g_singleton; } + // ISlangUnknown + SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } + SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) + SLANG_OVERRIDE; + + // ICastable + SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; + + // IArtifactHelper + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createArtifact( + const ArtifactDesc& desc, + const char* name, + IArtifact** outArtifact) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW ArtifactKind SLANG_MCALL getKindParent(ArtifactKind kind) SLANG_OVERRIDE; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getKindName(ArtifactKind kind) + SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL isKindDerivedFrom(ArtifactKind kind, ArtifactKind base) + SLANG_OVERRIDE; + + virtual SLANG_NO_THROW ArtifactPayload SLANG_MCALL getPayloadParent(ArtifactPayload payload) + SLANG_OVERRIDE; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getPayloadName(ArtifactPayload payload) + SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL + isPayloadDerivedFrom(ArtifactPayload payload, ArtifactPayload base) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW ArtifactStyle SLANG_MCALL getStyleParent(ArtifactStyle style) + SLANG_OVERRIDE; + virtual SLANG_NO_THROW UnownedStringSlice SLANG_MCALL getStyleName(ArtifactStyle style) + SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL + isStyleDerivedFrom(ArtifactStyle style, ArtifactStyle base) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createLockFile( + const CharSlice& nameBase, + IOSFileArtifactRepresentation** outLockFile) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL calcArtifactDescPath( + const ArtifactDesc& desc, + const char* basePath, + ISlangBlob** outPath) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + calcArtifactPath(IArtifact*, const char* basePath, ISlangBlob** outPath) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW ArtifactDesc SLANG_MCALL + makeDescForCompileTarget(SlangCompileTarget target) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW void SLANG_MCALL getCastable(ISlangUnknown* unk, ICastable** outCastable) + SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifactRepresentation( + IOSFileArtifactRepresentation::Kind kind, + const CharSlice& path, + IOSFileArtifactRepresentation* lockFile, + IOSFileArtifactRepresentation** outRep) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createExtFileArtifactRepresentation( + const CharSlice& path, + ISlangFileSystemExt* system, + IExtFileArtifactRepresentation** outRep) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL createOSFileArtifact( + const ArtifactDesc& desc, + const CharSlice& slice, + IArtifact** outArtifact) SLANG_OVERRIDE; + + static IArtifactHelper* getSingleton() { return &g_singleton; } protected: - void* getInterface(const Guid& guid); - void* getObject(const Guid& guid); + void* getInterface(const Guid& guid); + void* getObject(const Guid& guid); - static DefaultArtifactHelper g_singleton; + static DefaultArtifactHelper g_singleton; }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-impl.cpp b/source/compiler-core/slang-artifact-impl.cpp index d13421880..bb7584510 100644 --- a/source/compiler-core/slang-artifact-impl.cpp +++ b/source/compiler-core/slang-artifact-impl.cpp @@ -1,29 +1,27 @@ // slang-artifact-impl.cpp #include "slang-artifact-impl.h" -#include "slang-artifact-representation.h" - -#include "slang-artifact-util.h" +#include "../core/slang-castable.h" #include "slang-artifact-desc-util.h" - #include "slang-artifact-handler-impl.h" - +#include "slang-artifact-representation.h" +#include "slang-artifact-util.h" #include "slang-slice-allocator.h" -#include "../core/slang-castable.h" - -namespace Slang { +namespace Slang +{ -namespace { // anonymous +namespace +{ // anonymous /* Get a view as a slice of *raw* pointers */ -template +template SLANG_FORCE_INLINE ConstArrayView _getRawView(const List>& in) { - return makeConstArrayView((T*const*)in.getBuffer(), in.getCount()); + return makeConstArrayView((T* const*)in.getBuffer(), in.getCount()); } -} // anonymous +} // namespace /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Artifact !!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -38,8 +36,7 @@ void* Artifact::castAs(const Guid& guid) void* Artifact::getInterface(const Guid& uuid) { - if (uuid == ISlangUnknown::getTypeGuid() || - uuid == ICastable::getTypeGuid() || + if (uuid == ISlangUnknown::getTypeGuid() || uuid == ICastable::getTypeGuid() || uuid == IArtifact::getTypeGuid()) { return static_cast(this); @@ -96,7 +93,11 @@ SlangResult Artifact::requireFile(Keep keep, IOSFileArtifactRepresentation** out auto handler = _getHandler(); ComPtr castable; - SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation(this, IOSFileArtifactRepresentation::getTypeGuid(), keep, castable.writeRef())); + SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation( + this, + IOSFileArtifactRepresentation::getTypeGuid(), + keep, + castable.writeRef())); auto fileRep = as(castable); fileRep->addRef(); @@ -110,8 +111,12 @@ SlangResult Artifact::loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** auto handler = _getHandler(); ComPtr castable; - SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation(this, ISlangSharedLibrary::getTypeGuid(), keep, castable.writeRef())); - + SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation( + this, + ISlangSharedLibrary::getTypeGuid(), + keep, + castable.writeRef())); + auto lib = as(castable); lib->addRef(); @@ -133,10 +138,10 @@ void Artifact::clear(IArtifact::ContainedKind kind) { switch (kind) { - case ContainedKind::Associated: m_associated.clear(); break; - case ContainedKind::Representation: m_representations.clear(); break; - case ContainedKind::Children: m_children.clear(); break; - default: break; + case ContainedKind::Associated: m_associated.clear(); break; + case ContainedKind::Representation: m_representations.clear(); break; + case ContainedKind::Children: m_children.clear(); break; + default: break; } } @@ -144,14 +149,17 @@ void Artifact::removeAt(ContainedKind kind, Index i) { switch (kind) { - case ContainedKind::Associated: m_associated.removeAt(i); break; - case ContainedKind::Representation: m_representations.removeAt(i); break; - case ContainedKind::Children: m_children.removeAt(i); break; - default: break; + case ContainedKind::Associated: m_associated.removeAt(i); break; + case ContainedKind::Representation: m_representations.removeAt(i); break; + case ContainedKind::Children: m_children.removeAt(i); break; + default: break; } } -SlangResult Artifact::getOrCreateRepresentation(const Guid& typeGuid, ArtifactKeep keep, ICastable** outCastable) +SlangResult Artifact::getOrCreateRepresentation( + const Guid& typeGuid, + ArtifactKeep keep, + ICastable** outCastable) { auto handler = _getHandler(); return handler->getOrCreateRepresentation(this, typeGuid, keep, outCastable); @@ -162,7 +170,11 @@ SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob) auto handler = _getHandler(); ComPtr castable; - SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation(this, ISlangBlob::getTypeGuid(), keep, castable.writeRef())); + SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation( + this, + ISlangBlob::getTypeGuid(), + keep, + castable.writeRef())); ISlangBlob* blob = as(castable); blob->addRef(); @@ -205,9 +217,10 @@ void* Artifact::findRepresentation(ContainedKind kind, const Guid& guid) { switch (kind) { - case ContainedKind::Associated: return _findRepresentation(_getRawView(m_associated), guid); - case ContainedKind::Representation: return _findRepresentation(_getRawView(m_representations), guid); - case ContainedKind::Children: + case ContainedKind::Associated: return _findRepresentation(_getRawView(m_associated), guid); + case ContainedKind::Representation: + return _findRepresentation(_getRawView(m_representations), guid); + case ContainedKind::Children: { _requireChildren(); return _findRepresentation(_getRawView(m_children), guid); @@ -240,7 +253,9 @@ void Artifact::addRepresentationUnknown(ISlangUnknown* unk) SLANG_ASSERT(unk); { - const auto view = makeConstArrayView((ISlangUnknown*const*)m_representations.getBuffer(), m_representations.getCount()); + const auto view = makeConstArrayView( + (ISlangUnknown* const*)m_representations.getBuffer(), + m_representations.getCount()); if (view.indexOf(unk) >= 0) { SLANG_ASSERT_FAILURE("Already have this representation"); @@ -270,7 +285,7 @@ Slice Artifact::getRepresentations() return SliceUtil::asSlice(m_representations); } -void Artifact::setChildren(IArtifact*const* children, Count count) +void Artifact::setChildren(IArtifact* const* children, Count count) { m_expandResult = SLANG_OK; diff --git a/source/compiler-core/slang-artifact-impl.h b/source/compiler-core/slang-artifact-impl.h index 22547d3ef..a307a9d6d 100644 --- a/source/compiler-core/slang-artifact-impl.h +++ b/source/compiler-core/slang-artifact-impl.h @@ -2,34 +2,36 @@ #ifndef SLANG_ARTIFACT_IMPL_H #define SLANG_ARTIFACT_IMPL_H +#include "../core/slang-com-object.h" #include "slang-artifact.h" - #include "slang-com-helper.h" #include "slang-com-ptr.h" -#include "../core/slang-com-object.h" - namespace Slang { /* Discussion: -Another issue occurs around wanting to hold multiple kernels within a container. The problem here is that although through the desc -we can identify what target a kernel is for, there is no way of telling what stage it is for. +Another issue occurs around wanting to hold multiple kernels within a container. The problem here is +that although through the desc we can identify what target a kernel is for, there is no way of +telling what stage it is for. -When discussing the idea of a shader cache, one idea was to use a ISlangFileSystem (which could actually be a zip, or directory or in memory rep) -as the main structure. Within this it can contain kernels, and then a json manifest can describe what each of these actually are. +When discussing the idea of a shader cache, one idea was to use a ISlangFileSystem (which could +actually be a zip, or directory or in memory rep) as the main structure. Within this it can contain +kernels, and then a json manifest can describe what each of these actually are. -This all 'works', in that we can add an element of ISlangFileSystem with a desc of Container. Code that uses this can then go through the process -of finding, and getting the blob, and find from the manifest what it means. That does sound a little tedious though. Perhaps we just have an interface -that handles this detail, such that we search for that first. That interface is just attached to the artifact as an element. +This all 'works', in that we can add an element of ISlangFileSystem with a desc of Container. Code +that uses this can then go through the process of finding, and getting the blob, and find from the +manifest what it means. That does sound a little tedious though. Perhaps we just have an interface +that handles this detail, such that we search for that first. That interface is just attached to the +artifact as an element. */ class Artifact : public ComBaseObject, public IArtifact { public: SLANG_COM_BASE_IUNKNOWN_ALL - + /// ICastable virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; @@ -37,47 +39,71 @@ public: virtual SLANG_NO_THROW Desc SLANG_MCALL getDesc() SLANG_OVERRIDE { return m_desc; } virtual SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadBlob(Keep keep, ISlangBlob** outBlob) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFile(Keep keep, IOSFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW const char* SLANG_MCALL getName() SLANG_OVERRIDE { return m_name.getBuffer(); } - virtual SLANG_NO_THROW void SLANG_MCALL setName(const char* name) SLANG_OVERRIDE { m_name = name; } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadBlob(Keep keep, ISlangBlob** outBlob) + SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + requireFile(Keep keep, IOSFileArtifactRepresentation** outFileRep) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) SLANG_OVERRIDE; + + virtual SLANG_NO_THROW const char* SLANG_MCALL getName() SLANG_OVERRIDE + { + return m_name.getBuffer(); + } + virtual SLANG_NO_THROW void SLANG_MCALL setName(const char* name) SLANG_OVERRIDE + { + m_name = name; + } virtual SLANG_NO_THROW void SLANG_MCALL addAssociated(IArtifact* artifact) SLANG_OVERRIDE; virtual SLANG_NO_THROW Slice SLANG_MCALL getAssociated() SLANG_OVERRIDE; - + virtual SLANG_NO_THROW void SLANG_MCALL addRepresentation(ICastable* castable) SLANG_OVERRIDE; - virtual SLANG_NO_THROW void SLANG_MCALL addRepresentationUnknown(ISlangUnknown* rep) SLANG_OVERRIDE; + virtual SLANG_NO_THROW void SLANG_MCALL addRepresentationUnknown(ISlangUnknown* rep) + SLANG_OVERRIDE; virtual SLANG_NO_THROW Slice SLANG_MCALL getRepresentations() SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation(const Guid& typeGuid, ArtifactKeep keep, ICastable** outCastable) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation( + const Guid& typeGuid, + ArtifactKeep keep, + ICastable** outCastable) SLANG_OVERRIDE; virtual SLANG_NO_THROW IArtifactHandler* SLANG_MCALL getHandler() SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL setHandler(IArtifactHandler* handler) SLANG_OVERRIDE; virtual SLANG_NO_THROW Slice SLANG_MCALL getChildren() SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getExpandChildrenResult() SLANG_OVERRIDE { return m_expandResult; } - virtual SLANG_NO_THROW void SLANG_MCALL setChildren(IArtifact*const* children, Count count) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getExpandChildrenResult() SLANG_OVERRIDE + { + return m_expandResult; + } + virtual SLANG_NO_THROW void SLANG_MCALL setChildren(IArtifact* const* children, Count count) + SLANG_OVERRIDE; virtual SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren() SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL addChild(IArtifact* artifact) SLANG_OVERRIDE; - virtual SLANG_NO_THROW void* SLANG_MCALL findRepresentation(ContainedKind kind, const Guid& unk) SLANG_OVERRIDE; + virtual SLANG_NO_THROW void* SLANG_MCALL findRepresentation(ContainedKind kind, const Guid& unk) + SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL clear(ContainedKind kind) SLANG_OVERRIDE; virtual SLANG_NO_THROW void SLANG_MCALL removeAt(ContainedKind kind, Index i) SLANG_OVERRIDE; - static ComPtr create(const Desc& desc) { return ComPtr(new Artifact(desc)); } - static ComPtr create(const Desc& desc, const UnownedStringSlice& name) { return ComPtr(new Artifact(desc, name)); } - -protected: + static ComPtr create(const Desc& desc) + { + return ComPtr(new Artifact(desc)); + } + static ComPtr create(const Desc& desc, const UnownedStringSlice& name) + { + return ComPtr(new Artifact(desc, name)); + } +protected: /// Ctor - Artifact(const Desc& desc, const UnownedStringSlice& name) : - m_desc(desc), - m_name(name) - {} - Artifact(const Desc& desc) : - m_desc(desc) - {} + Artifact(const Desc& desc, const UnownedStringSlice& name) + : m_desc(desc), m_name(name) + { + } + Artifact(const Desc& desc) + : m_desc(desc) + { + } IArtifactHandler* _getHandler(); void _requireChildren(); @@ -85,15 +111,16 @@ protected: void* getInterface(const Guid& uuid); void* getObject(const Guid& uuid); - Desc m_desc; ///< Description of the artifact - String m_name; ///< Name of this artifact + Desc m_desc; ///< Description of the artifact + String m_name; ///< Name of this artifact SlangResult m_expandResult = SLANG_E_UNINITIALIZED; - ComPtr m_handler; ///< The handler. Can be nullptr and then default handler is used. + ComPtr + m_handler; ///< The handler. Can be nullptr and then default handler is used. - List> m_representations; ///< All the representation of this artifact - List> m_associated; ///< All the items associated with this artifact - List> m_children; ///< All the child artifacts owned + List> m_representations; ///< All the representation of this artifact + List> m_associated; ///< All the items associated with this artifact + List> m_children; ///< All the child artifacts owned }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-representation-impl.cpp b/source/compiler-core/slang-artifact-representation-impl.cpp index 85563fe61..648e4d8c1 100644 --- a/source/compiler-core/slang-artifact-representation-impl.cpp +++ b/source/compiler-core/slang-artifact-representation-impl.cpp @@ -1,24 +1,21 @@ // slang-artifact-representation-impl.cpp #include "slang-artifact-representation-impl.h" +#include "../core/slang-array-view.h" +#include "../core/slang-castable.h" #include "../core/slang-file-system.h" - -#include "../core/slang-type-text-util.h" #include "../core/slang-io.h" -#include "../core/slang-array-view.h" - +#include "../core/slang-type-text-util.h" #include "slang-artifact-util.h" -#include "../core/slang-castable.h" - -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ExtFileArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! */ void* ExtFileArtifactRepresentation::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IArtifactRepresentation::getTypeGuid() || guid == IPathArtifactRepresentation::getTypeGuid() || guid == IExtFileArtifactRepresentation::getTypeGuid()) @@ -43,7 +40,9 @@ void* ExtFileArtifactRepresentation::castAs(const Guid& guid) return getObject(guid); } -SlangResult ExtFileArtifactRepresentation::createRepresentation(const Guid& typeGuid, ICastable** outCastable) +SlangResult ExtFileArtifactRepresentation::createRepresentation( + const Guid& typeGuid, + ICastable** outCastable) { // We can convert into a blob only, and only if we have a path // If it's referenced by a name only, it's a file that *can't* be loaded as a blob in general. @@ -72,7 +71,9 @@ const char* ExtFileArtifactRepresentation::getUniqueIdentity() if (m_uniqueIdentity.getLength() == 0) { ComPtr uniqueIdentityBlob; - if (SLANG_FAILED(m_fileSystem->getFileUniqueIdentity(m_path.getBuffer(), uniqueIdentityBlob.writeRef()))) + if (SLANG_FAILED(m_fileSystem->getFileUniqueIdentity( + m_path.getBuffer(), + uniqueIdentityBlob.writeRef()))) { return nullptr; } @@ -82,12 +83,12 @@ const char* ExtFileArtifactRepresentation::getUniqueIdentity() return m_uniqueIdentity.getLength() ? m_uniqueIdentity.getBuffer() : nullptr; } -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SourceBlobWithPathArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SourceBlobWithPathArtifactRepresentation + * !!!!!!!!!!!!!!!!!!!!!!!!!!! */ void* SourceBlobWithPathInfoArtifactRepresentation::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IArtifactRepresentation::getTypeGuid() || guid == IPathArtifactRepresentation::getTypeGuid()) { @@ -111,7 +112,9 @@ void* SourceBlobWithPathInfoArtifactRepresentation::castAs(const Guid& guid) return getObject(guid); } -SlangResult SourceBlobWithPathInfoArtifactRepresentation::createRepresentation(const Guid& typeGuid, ICastable** outCastable) +SlangResult SourceBlobWithPathInfoArtifactRepresentation::createRepresentation( + const Guid& typeGuid, + ICastable** outCastable) { // We can convert into a blob only. if (typeGuid != ISlangBlob::getTypeGuid()) @@ -132,8 +135,7 @@ SlangResult SourceBlobWithPathInfoArtifactRepresentation::createRepresentation(c void* OSFileArtifactRepresentation::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IArtifactRepresentation::getTypeGuid() || guid == IPathArtifactRepresentation::getTypeGuid() || guid == IOSFileArtifactRepresentation::getTypeGuid()) @@ -149,7 +151,7 @@ void* OSFileArtifactRepresentation::getObject(const Guid& guid) return nullptr; } -/* static */ISlangMutableFileSystem* OSFileArtifactRepresentation::_getFileSystem() +/* static */ ISlangMutableFileSystem* OSFileArtifactRepresentation::_getFileSystem() { return OSFileSystem::getMutableSingleton(); } @@ -163,12 +165,13 @@ void* OSFileArtifactRepresentation::castAs(const Guid& guid) return getObject(guid); } -SlangResult OSFileArtifactRepresentation::createRepresentation(const Guid& typeGuid, ICastable** outCastable) +SlangResult OSFileArtifactRepresentation::createRepresentation( + const Guid& typeGuid, + ICastable** outCastable) { // We can convert into a blob only, and only if we have a path // If it's referenced by a name only, it's a file that *can't* be loaded as a blob in general. - if (typeGuid != ISlangBlob::getTypeGuid() || - m_kind == Kind::NameOnly) + if (typeGuid != ISlangBlob::getTypeGuid() || m_kind == Kind::NameOnly) { return SLANG_E_NOT_AVAILABLE; } @@ -185,9 +188,9 @@ SlangResult OSFileArtifactRepresentation::createRepresentation(const Guid& typeG bool OSFileArtifactRepresentation::exists() { // TODO(JS): - // If it's a name only it's hard to know what exists should do. It can't *check* because it relies on the 'system' doing - // the actual location. We could ask the IArtifactUtil, and that could change the behavior. - // For now we just assume it does. + // If it's a name only it's hard to know what exists should do. It can't *check* because it + // relies on the 'system' doing the actual location. We could ask the IArtifactUtil, and that + // could change the behavior. For now we just assume it does. if (m_kind == Kind::NameOnly) { return true; @@ -209,7 +212,9 @@ const char* OSFileArtifactRepresentation::getUniqueIdentity() auto fileSystem = _getFileSystem(); ComPtr uniqueIdentityBlob; - if (SLANG_FAILED(fileSystem->getFileUniqueIdentity(m_path.getBuffer(), uniqueIdentityBlob.writeRef()))) + if (SLANG_FAILED(fileSystem->getFileUniqueIdentity( + m_path.getBuffer(), + uniqueIdentityBlob.writeRef()))) { return nullptr; } @@ -236,11 +241,12 @@ OSFileArtifactRepresentation::~OSFileArtifactRepresentation() } } -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! PostEmitMetadataArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! PostEmitMetadataArtifactRepresentation !!!!!!!!!!!!!!!!!!!!!!!!!!! + */ void* ObjectArtifactRepresentation::castAs(const Guid& guid) { - + if (auto ptr = getInterface(guid)) { return ptr; @@ -250,8 +256,7 @@ void* ObjectArtifactRepresentation::castAs(const Guid& guid) void* ObjectArtifactRepresentation::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IArtifactRepresentation::getTypeGuid()) { return static_cast(this); diff --git a/source/compiler-core/slang-artifact-representation-impl.h b/source/compiler-core/slang-artifact-representation-impl.h index 034084950..5e28d42f3 100644 --- a/source/compiler-core/slang-artifact-representation-impl.h +++ b/source/compiler-core/slang-artifact-representation-impl.h @@ -2,14 +2,11 @@ #ifndef SLANG_ARTIFACT_REPRESENTATION_IMPL_H #define SLANG_ARTIFACT_REPRESENTATION_IMPL_H +#include "../core/slang-com-object.h" +#include "../core/slang-memory-arena.h" #include "slang-artifact-representation.h" - #include "slang-com-helper.h" #include "slang-com-ptr.h" - -#include "../core/slang-com-object.h" -#include "../core/slang-memory-arena.h" - #include "slang-source-loc.h" namespace Slang @@ -27,29 +24,43 @@ public: SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; // IArtifactRepresentation - SLANG_NO_THROW SlangResult SLANG_MCALL createRepresentation(const Guid& typeGuid, ICastable** outCastable) SLANG_OVERRIDE; + SLANG_NO_THROW SlangResult SLANG_MCALL + createRepresentation(const Guid& typeGuid, ICastable** outCastable) SLANG_OVERRIDE; SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE; // IPathArtifactRepresentation - virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE { return m_path.getBuffer(); } - virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() SLANG_OVERRIDE { return SLANG_PATH_TYPE_FILE; } + virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE + { + return m_path.getBuffer(); + } + virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() SLANG_OVERRIDE + { + return SLANG_PATH_TYPE_FILE; + } virtual SLANG_NO_THROW const char* SLANG_MCALL getUniqueIdentity() SLANG_OVERRIDE; // IOSFileArtifactRepresentation virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() SLANG_OVERRIDE { return m_kind; } virtual SLANG_NO_THROW void SLANG_MCALL disown() SLANG_OVERRIDE; - virtual SLANG_NO_THROW IOSFileArtifactRepresentation* SLANG_MCALL getLockFile() SLANG_OVERRIDE { return m_lockFile; } + virtual SLANG_NO_THROW IOSFileArtifactRepresentation* SLANG_MCALL getLockFile() SLANG_OVERRIDE + { + return m_lockFile; + } - OSFileArtifactRepresentation(Kind kind, const UnownedStringSlice& path, IOSFileArtifactRepresentation* lockFile): - m_kind(kind), - m_lockFile(lockFile), - m_path(path) + OSFileArtifactRepresentation( + Kind kind, + const UnownedStringSlice& path, + IOSFileArtifactRepresentation* lockFile) + : m_kind(kind), m_lockFile(lockFile), m_path(path) { } ~OSFileArtifactRepresentation(); - static ComPtr create(Kind kind, const UnownedStringSlice& path, IOSFileArtifactRepresentation* lockFile) + static ComPtr create( + Kind kind, + const UnownedStringSlice& path, + IOSFileArtifactRepresentation* lockFile) { return ComPtr(new ThisType(kind, path, lockFile)); } @@ -58,7 +69,7 @@ protected: void* getInterface(const Guid& uuid); void* getObject(const Guid& uuid); - /// True if the file is owned + /// True if the file is owned bool _isOwned() const { return Index(m_kind) >= Index(Kind::Owned); } static ISlangMutableFileSystem* _getFileSystem(); @@ -82,24 +93,35 @@ public: SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; // IArtifactRepresentation - SLANG_NO_THROW SlangResult SLANG_MCALL createRepresentation(const Guid& typeGuid, ICastable** outCastable) SLANG_OVERRIDE; + SLANG_NO_THROW SlangResult SLANG_MCALL + createRepresentation(const Guid& typeGuid, ICastable** outCastable) SLANG_OVERRIDE; SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE; // IPathArtifactRepresentation - virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE { return m_path.getBuffer(); } - virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() SLANG_OVERRIDE { return SLANG_PATH_TYPE_FILE; } + virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE + { + return m_path.getBuffer(); + } + virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() SLANG_OVERRIDE + { + return SLANG_PATH_TYPE_FILE; + } virtual SLANG_NO_THROW const char* SLANG_MCALL getUniqueIdentity() SLANG_OVERRIDE; - + // IExtFileArtifactRepresentation - virtual SLANG_NO_THROW ISlangFileSystemExt* SLANG_MCALL getFileSystem() SLANG_OVERRIDE { return m_fileSystem; } + virtual SLANG_NO_THROW ISlangFileSystemExt* SLANG_MCALL getFileSystem() SLANG_OVERRIDE + { + return m_fileSystem; + } - ExtFileArtifactRepresentation(const UnownedStringSlice& path, ISlangFileSystemExt* fileSystem) : - m_path(path), - m_fileSystem(fileSystem) + ExtFileArtifactRepresentation(const UnownedStringSlice& path, ISlangFileSystemExt* fileSystem) + : m_path(path), m_fileSystem(fileSystem) { } - static ComPtr create(const UnownedStringSlice& path, ISlangFileSystemExt* fileSystem) + static ComPtr create( + const UnownedStringSlice& path, + ISlangFileSystemExt* fileSystem) { return ComPtr(new ThisType(path, fileSystem)); } @@ -113,7 +135,8 @@ protected: ComPtr m_fileSystem; }; -class SourceBlobWithPathInfoArtifactRepresentation : public ComBaseObject, public IPathArtifactRepresentation +class SourceBlobWithPathInfoArtifactRepresentation : public ComBaseObject, + public IPathArtifactRepresentation { public: typedef SourceBlobWithPathInfoArtifactRepresentation ThisType; @@ -124,21 +147,32 @@ public: SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; // IArtifactRepresentation - SLANG_NO_THROW SlangResult SLANG_MCALL createRepresentation(const Guid& typeGuid, ICastable** outCastable) SLANG_OVERRIDE; + SLANG_NO_THROW SlangResult SLANG_MCALL + createRepresentation(const Guid& typeGuid, ICastable** outCastable) SLANG_OVERRIDE; SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE { return false; } // IPathArtifactRepresentation - virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE { return m_pathInfo.getName().getBuffer(); } - virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() SLANG_OVERRIDE { return SLANG_PATH_TYPE_FILE; } - virtual SLANG_NO_THROW const char* SLANG_MCALL getUniqueIdentity() SLANG_OVERRIDE { return m_pathInfo.hasUniqueIdentity() ? m_pathInfo.uniqueIdentity.getBuffer() : nullptr; } + virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() SLANG_OVERRIDE + { + return m_pathInfo.getName().getBuffer(); + } + virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() SLANG_OVERRIDE + { + return SLANG_PATH_TYPE_FILE; + } + virtual SLANG_NO_THROW const char* SLANG_MCALL getUniqueIdentity() SLANG_OVERRIDE + { + return m_pathInfo.hasUniqueIdentity() ? m_pathInfo.uniqueIdentity.getBuffer() : nullptr; + } - SourceBlobWithPathInfoArtifactRepresentation(const PathInfo& pathInfo, ISlangBlob* sourceBlob) : - m_pathInfo(pathInfo), - m_blob(sourceBlob) + SourceBlobWithPathInfoArtifactRepresentation(const PathInfo& pathInfo, ISlangBlob* sourceBlob) + : m_pathInfo(pathInfo), m_blob(sourceBlob) { } - static ComPtr create(const PathInfo& pathInfo, ISlangBlob* sourceBlob) + static ComPtr create( + const PathInfo& pathInfo, + ISlangBlob* sourceBlob) { return ComPtr(new ThisType(pathInfo, sourceBlob)); } @@ -151,34 +185,40 @@ protected: ComPtr m_blob; }; -/* This allows wrapping any object to be an artifact representation. +/* This allows wrapping any object to be an artifact representation. -NOTE! Only allows casting from a single guid. Passing a RefObject across an ABI boundary remains risky! +NOTE! Only allows casting from a single guid. Passing a RefObject across an ABI boundary remains +risky! */ class ObjectArtifactRepresentation : public ComBaseObject, public IArtifactRepresentation { public: - SLANG_CLASS_GUID(0xb9d5af57, 0x725b, 0x45f8, { 0xac, 0xed, 0x18, 0xf4, 0xa8, 0x4b, 0xf4, 0x73 }) + SLANG_CLASS_GUID(0xb9d5af57, 0x725b, 0x45f8, {0xac, 0xed, 0x18, 0xf4, 0xa8, 0x4b, 0xf4, 0x73}) SLANG_COM_BASE_IUNKNOWN_ALL // ICastable SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; // IArtifactRepresentation - SLANG_NO_THROW SlangResult SLANG_MCALL createRepresentation(const Guid& guid, ICastable** outCastable) SLANG_OVERRIDE { SLANG_UNUSED(guid); SLANG_UNUSED(outCastable); return SLANG_E_NOT_AVAILABLE; } + SLANG_NO_THROW SlangResult SLANG_MCALL + createRepresentation(const Guid& guid, ICastable** outCastable) SLANG_OVERRIDE + { + SLANG_UNUSED(guid); + SLANG_UNUSED(outCastable); + return SLANG_E_NOT_AVAILABLE; + } SLANG_NO_THROW bool SLANG_MCALL exists() SLANG_OVERRIDE { return m_object; } - ObjectArtifactRepresentation(const Guid& typeGuid, RefObject* obj): - m_typeGuid(typeGuid), - m_object(obj) + ObjectArtifactRepresentation(const Guid& typeGuid, RefObject* obj) + : m_typeGuid(typeGuid), m_object(obj) { } void* getInterface(const Guid& uuid); void* getObject(const Guid& uuid); - - Guid m_typeGuid; ///< Will return m_object if a cast to m_typeGuid is given - RefPtr m_object; ///< The object + + Guid m_typeGuid; ///< Will return m_object if a cast to m_typeGuid is given + RefPtr m_object; ///< The object }; } // namespace Slang diff --git a/source/compiler-core/slang-artifact-representation.h b/source/compiler-core/slang-artifact-representation.h index 3e7659058..719571806 100644 --- a/source/compiler-core/slang-artifact-representation.h +++ b/source/compiler-core/slang-artifact-representation.h @@ -10,49 +10,65 @@ namespace Slang /* Base interface for types that have a path. */ class IPathArtifactRepresentation : public IArtifactRepresentation { - SLANG_COM_INTERFACE(0xcb1c188c, 0x7e48, 0x43eb, { 0xb0, 0x9a, 0xa1, 0x6e, 0xef, 0xd4, 0x9b, 0xef }); + SLANG_COM_INTERFACE( + 0xcb1c188c, + 0x7e48, + 0x43eb, + {0xb0, 0x9a, 0xa1, 0x6e, 0xef, 0xd4, 0x9b, 0xef}); - /// The path + /// The path virtual SLANG_NO_THROW const char* SLANG_MCALL getPath() = 0; - /// Get type + /// Get type virtual SLANG_NO_THROW SlangPathType SLANG_MCALL getPathType() = 0; - /// Returns the unique identity. If a unique identity is not supported - /// or available will return nullptr. + /// Returns the unique identity. If a unique identity is not supported + /// or available will return nullptr. virtual SLANG_NO_THROW const char* SLANG_MCALL getUniqueIdentity() = 0; }; /* Represents a path to a file held on an ISlangFileSystem. */ class IExtFileArtifactRepresentation : public IPathArtifactRepresentation { - SLANG_COM_INTERFACE(0xacd65576, 0xb09d, 0x4ac9, { 0xa5, 0x93, 0xeb, 0xf8, 0x9b, 0xd7, 0x11, 0xfd }); + SLANG_COM_INTERFACE( + 0xacd65576, + 0xb09d, + 0x4ac9, + {0xa5, 0x93, 0xeb, 0xf8, 0x9b, 0xd7, 0x11, 0xfd}); - /// File system that holds the item along the path. + /// File system that holds the item along the path. virtual SLANG_NO_THROW ISlangFileSystemExt* SLANG_MCALL getFileSystem() = 0; }; -/* +/* A representation as a file on the OS file system. */ class IOSFileArtifactRepresentation : public IPathArtifactRepresentation { public: - SLANG_COM_INTERFACE(0xc7d7d3a4, 0x8683, 0x44b5, { 0x87, 0x96, 0xdf, 0xba, 0x9b, 0xc3, 0xf1, 0x7b }); + SLANG_COM_INTERFACE( + 0xc7d7d3a4, + 0x8683, + 0x44b5, + {0x87, 0x96, 0xdf, 0xba, 0x9b, 0xc3, 0xf1, 0x7b}); /* Determines ownership and other characteristics of the OS 'file' */ enum class Kind { - Reference, ///< References a file on the file system - NameOnly, ///< Typically used for items that can be found by the 'system'. The path is just a name, and cannot typically be loaded as a blob. - Owned, ///< File is *owned* by this instance and will be deleted when goes out of scope - Lock, ///< An owned type, indicates potentially in part may only exist to 'lock' a path for a temporary file. Other files might exists based on the 'lock' path. + Reference, ///< References a file on the file system + NameOnly, ///< Typically used for items that can be found by the 'system'. The path is just + ///< a name, and cannot typically be loaded as a blob. + Owned, ///< File is *owned* by this instance and will be deleted when goes out of scope + Lock, ///< An owned type, indicates potentially in part may only exist to 'lock' a path for + ///< a temporary file. Other files might exists based on the 'lock' path. CountOf, }; - /// The the kind of file. - virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() = 0; - /// Makes the file no longer owned. Only applicable for Owned/Lock and they will become 'Reference' + /// The the kind of file. + virtual SLANG_NO_THROW Kind SLANG_MCALL getKind() = 0; + /// Makes the file no longer owned. Only applicable for Owned/Lock and they will become + /// 'Reference' virtual SLANG_NO_THROW void SLANG_MCALL disown() = 0; - /// Gets the 'lock file' if any associated with this file. Returns nullptr if there isn't one. - /// If this file is based on a 'lock file', the lock file must stay in scope at least as long as this does. + /// Gets the 'lock file' if any associated with this file. Returns nullptr if there isn't one. + /// If this file is based on a 'lock file', the lock file must stay in scope at least as long as + /// this does. virtual SLANG_NO_THROW IOSFileArtifactRepresentation* SLANG_MCALL getLockFile() = 0; }; diff --git a/source/compiler-core/slang-artifact-util.cpp b/source/compiler-core/slang-artifact-util.cpp index e03f02e1e..703f8fddb 100644 --- a/source/compiler-core/slang-artifact-util.cpp +++ b/source/compiler-core/slang-artifact-util.cpp @@ -1,15 +1,14 @@ // slang-artifact-util.cpp #include "slang-artifact-util.h" -#include "slang-artifact-impl.h" -#include "slang-artifact-representation-impl.h" - -#include "slang-artifact-desc-util.h" - #include "../core/slang-castable.h" #include "../core/slang-io.h" +#include "slang-artifact-desc-util.h" +#include "slang-artifact-impl.h" +#include "slang-artifact-representation-impl.h" -namespace Slang { +namespace Slang +{ static bool _checkSelf(ArtifactUtil::FindStyle findStyle) { @@ -23,36 +22,39 @@ static bool _checkChildren(ArtifactUtil::FindStyle findStyle) static bool _checkRecursive(ArtifactUtil::FindStyle findStyle) { - return findStyle == ArtifactUtil::FindStyle::Recursive || - findStyle == ArtifactUtil::FindStyle::ChildrenRecursive; + return findStyle == ArtifactUtil::FindStyle::Recursive || + findStyle == ArtifactUtil::FindStyle::ChildrenRecursive; } - + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactUtil !!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */ComPtr ArtifactUtil::createArtifact(const ArtifactDesc& desc, const char* name) +/* static */ ComPtr ArtifactUtil::createArtifact( + const ArtifactDesc& desc, + const char* name) { auto artifact = createArtifact(desc); artifact->setName(name); return artifact; } -/* static */ComPtr ArtifactUtil::createArtifact(const ArtifactDesc& desc) +/* static */ ComPtr ArtifactUtil::createArtifact(const ArtifactDesc& desc) { return Artifact::create(desc); } -/* static */ComPtr ArtifactUtil::createArtifactForCompileTarget(SlangCompileTarget target) +/* static */ ComPtr ArtifactUtil::createArtifactForCompileTarget( + SlangCompileTarget target) { auto desc = ArtifactDescUtil::makeDescForCompileTarget(target); return createArtifact(desc); } -/* static */bool ArtifactUtil::isSignificant(IArtifact* artifact) +/* static */ bool ArtifactUtil::isSignificant(IArtifact* artifact) { return isSignificant(artifact->getDesc()); } -/* static */bool ArtifactUtil::isSignificant(const ArtifactDesc& desc) +/* static */ bool ArtifactUtil::isSignificant(const ArtifactDesc& desc) { // Containers are not significant as of themselves, they may contain something tho if (isDerivedFrom(desc.kind, ArtifactKind::Container)) @@ -61,16 +63,14 @@ static bool _checkRecursive(ArtifactUtil::FindStyle findStyle) } // If it has no payload.. we are done - if (desc.payload == ArtifactPayload::None || - desc.payload == ArtifactPayload::Invalid) + if (desc.payload == ArtifactPayload::None || desc.payload == ArtifactPayload::Invalid) { return false; } // If it's binary like or assembly/source we it's significant if (isDerivedFrom(desc.kind, ArtifactKind::CompileBinary) || - desc.kind == ArtifactKind::Assembly || - desc.kind == ArtifactKind::Source) + desc.kind == ArtifactKind::Assembly || desc.kind == ArtifactKind::Source) { return true; } @@ -93,15 +93,19 @@ static bool _checkRecursive(ArtifactUtil::FindStyle findStyle) } -/* static */bool ArtifactUtil::isSignificant(IArtifact* artifact, void* data) +/* static */ bool ArtifactUtil::isSignificant(IArtifact* artifact, void* data) { SLANG_UNUSED(data); return isSignificant(artifact->getDesc()); } -/* static */IArtifact* ArtifactUtil::findSignificant(IArtifact* artifact) -{ - return findArtifactByPredicate(artifact, FindStyle::SelfOrChildren, &ArtifactUtil::isSignificant, nullptr); +/* static */ IArtifact* ArtifactUtil::findSignificant(IArtifact* artifact) +{ + return findArtifactByPredicate( + artifact, + FindStyle::SelfOrChildren, + &ArtifactUtil::isSignificant, + nullptr); } UnownedStringSlice ArtifactUtil::findPath(IArtifact* artifact) @@ -122,7 +126,7 @@ UnownedStringSlice ArtifactUtil::findPath(IArtifact* artifact) { if (auto pathRep = as(rep)) { - if (pathRep->getPathType() == SLANG_PATH_TYPE_FILE && + if (pathRep->getPathType() == SLANG_PATH_TYPE_FILE && (bestRep == nullptr || as(rep))) { bestRep = pathRep; @@ -130,11 +134,12 @@ UnownedStringSlice ArtifactUtil::findPath(IArtifact* artifact) } } - const UnownedStringSlice name = bestRep ? UnownedStringSlice(bestRep->getPath()) : UnownedStringSlice(); + const UnownedStringSlice name = + bestRep ? UnownedStringSlice(bestRep->getPath()) : UnownedStringSlice(); return name.getLength() ? name : UnownedStringSlice(); } -/* static */UnownedStringSlice ArtifactUtil::inferExtension(IArtifact* artifact) +/* static */ UnownedStringSlice ArtifactUtil::inferExtension(IArtifact* artifact) { const UnownedStringSlice path = findPath(artifact); if (path.getLength()) @@ -148,14 +153,17 @@ UnownedStringSlice ArtifactUtil::findPath(IArtifact* artifact) return UnownedStringSlice(); } -/* static */UnownedStringSlice ArtifactUtil::findName(IArtifact* artifact) +/* static */ UnownedStringSlice ArtifactUtil::findName(IArtifact* artifact) { const UnownedStringSlice path = findPath(artifact); const Index pos = Path::findLastSeparatorIndex(path); return (pos >= 0) ? path.tail(pos + 1) : path; } -static SlangResult _calcInferred(IArtifact* artifact, const UnownedStringSlice& basePath, StringBuilder& outPath) +static SlangResult _calcInferred( + IArtifact* artifact, + const UnownedStringSlice& basePath, + StringBuilder& outPath) { auto ext = ArtifactUtil::inferExtension(artifact); @@ -175,7 +183,10 @@ static SlangResult _calcInferred(IArtifact* artifact, const UnownedStringSlice& return SLANG_OK; } -/* static */SlangResult ArtifactUtil::calcPath(IArtifact* artifact, const UnownedStringSlice& basePath, StringBuilder& outPath) +/* static */ SlangResult ArtifactUtil::calcPath( + IArtifact* artifact, + const UnownedStringSlice& basePath, + StringBuilder& outPath) { if (ArtifactDescUtil::hasDefinedNameForDesc(artifact->getDesc())) { @@ -187,7 +198,10 @@ static SlangResult _calcInferred(IArtifact* artifact, const UnownedStringSlice& } } -/* static */SlangResult ArtifactUtil::calcName(IArtifact* artifact, const UnownedStringSlice& baseName, StringBuilder& outName) +/* static */ SlangResult ArtifactUtil::calcName( + IArtifact* artifact, + const UnownedStringSlice& baseName, + StringBuilder& outName) { if (ArtifactDescUtil::hasDefinedNameForDesc(artifact->getDesc())) { @@ -223,22 +237,39 @@ static bool _isName(IArtifact* artifact, void* data) return ::strcmp(name, artifactName) == 0; } -/* static */IArtifact* ArtifactUtil::findArtifactByDerivedDesc(IArtifact* artifact, FindStyle findStyle, const ArtifactDesc& desc) +/* static */ IArtifact* ArtifactUtil::findArtifactByDerivedDesc( + IArtifact* artifact, + FindStyle findStyle, + const ArtifactDesc& desc) { - return findArtifactByPredicate(artifact, findStyle, _isByDerivedDesc, &const_cast(desc)); + return findArtifactByPredicate( + artifact, + findStyle, + _isByDerivedDesc, + &const_cast(desc)); } -/* static */IArtifact* ArtifactUtil::findArtifactByName(IArtifact* artifact, FindStyle findStyle, const char* name) +/* static */ IArtifact* ArtifactUtil::findArtifactByName( + IArtifact* artifact, + FindStyle findStyle, + const char* name) { return findArtifactByPredicate(artifact, findStyle, _isName, const_cast(name)); } -/* static */IArtifact* ArtifactUtil::findArtifactByDesc(IArtifact* artifact, FindStyle findStyle, const ArtifactDesc& desc) +/* static */ IArtifact* ArtifactUtil::findArtifactByDesc( + IArtifact* artifact, + FindStyle findStyle, + const ArtifactDesc& desc) { return findArtifactByPredicate(artifact, findStyle, _isDesc, &const_cast(desc)); } -/* static */IArtifact* ArtifactUtil::findArtifactByPredicate(IArtifact* artifact, FindStyle findStyle, FindFunc func, void* data) +/* static */ IArtifact* ArtifactUtil::findArtifactByPredicate( + IArtifact* artifact, + FindStyle findStyle, + FindFunc func, + void* data) { if (_checkSelf(findStyle) && func(artifact, data)) { @@ -250,7 +281,7 @@ static bool _isName(IArtifact* artifact, void* data) return nullptr; } - // Expand the children so we can search them + // Expand the children so we can search them artifact->expandChildren(); auto children = artifact->getChildren(); @@ -268,38 +299,45 @@ static bool _isName(IArtifact* artifact, void* data) } } - // If it's recursive, we check all the children of children + // If it's recursive, we check all the children of children if (_checkRecursive(findStyle)) { for (auto child : children) { - if (auto found = findArtifactByPredicate(child, FindStyle::ChildrenRecursive, func, data)) + if (auto found = + findArtifactByPredicate(child, FindStyle::ChildrenRecursive, func, data)) { return found; } } } - + return nullptr; } -/* static */void ArtifactUtil::addAssociated(IArtifact* artifact, IArtifactPostEmitMetadata* metadata) +/* static */ void ArtifactUtil::addAssociated( + IArtifact* artifact, + IArtifactPostEmitMetadata* metadata) { if (metadata) { - auto metadataArtifact = ArtifactUtil::createArtifact(ArtifactDesc::make(ArtifactKind::Instance, ArtifactPayload::PostEmitMetadata)); + auto metadataArtifact = ArtifactUtil::createArtifact( + ArtifactDesc::make(ArtifactKind::Instance, ArtifactPayload::PostEmitMetadata)); metadataArtifact->addRepresentation(metadata); artifact->addAssociated(metadataArtifact); } } -/* static */void ArtifactUtil::addAssociated(IArtifact* artifact, IArtifactDiagnostics* diagnostics) +/* static */ void ArtifactUtil::addAssociated( + IArtifact* artifact, + IArtifactDiagnostics* diagnostics) { if (diagnostics) { - auto diagnosticsArtifact = ArtifactUtil::createArtifact(ArtifactDesc::make(ArtifactKind::Instance, ArtifactPayload::Diagnostics)); + auto diagnosticsArtifact = ArtifactUtil::createArtifact( + ArtifactDesc::make(ArtifactKind::Instance, ArtifactPayload::Diagnostics)); diagnosticsArtifact->addRepresentation(diagnostics); - artifact->addAssociated(diagnosticsArtifact); + artifact->addAssociated(diagnosticsArtifact); } } diff --git a/source/compiler-core/slang-artifact-util.h b/source/compiler-core/slang-artifact-util.h index 5341f309b..538affcdb 100644 --- a/source/compiler-core/slang-artifact-util.h +++ b/source/compiler-core/slang-artifact-util.h @@ -2,10 +2,9 @@ #ifndef SLANG_ARTIFACT_UTIL_H #define SLANG_ARTIFACT_UTIL_H -#include "slang-artifact.h" -#include "slang-artifact-representation.h" #include "slang-artifact-associated.h" - +#include "slang-artifact-representation.h" +#include "slang-artifact.h" #include "slang-com-ptr.h" namespace Slang @@ -17,63 +16,86 @@ struct ArtifactUtil enum class FindStyle : uint8_t { - Self, ///< Just on self - SelfOrChildren, ///< Self, or if container just the children - Recursive, ///< On self plus any children recursively - Children, ///< Only on children - ChildrenRecursive, ///< Only on children recursively + Self, ///< Just on self + SelfOrChildren, ///< Self, or if container just the children + Recursive, ///< On self plus any children recursively + Children, ///< Only on children + ChildrenRecursive, ///< Only on children recursively }; - /// Find an artifact that matches desc allowing derivations. Flags is ignored - static IArtifact* findArtifactByDerivedDesc(IArtifact* artifact, FindStyle findStyle, const ArtifactDesc& desc); - /// Find an artifact that predicate matches - static IArtifact* findArtifactByPredicate(IArtifact* artifact, FindStyle findStyle, FindFunc func, void* data); - /// Find by name - static IArtifact* findArtifactByName(IArtifact* artifact, FindStyle findStyle, const char* name); - /// Find by desc exactly - static IArtifact* findArtifactByDesc(IArtifact* artifact, FindStyle findStyle, const ArtifactDesc& desc); - - /// Creates an empty artifact for a type + /// Find an artifact that matches desc allowing derivations. Flags is ignored + static IArtifact* findArtifactByDerivedDesc( + IArtifact* artifact, + FindStyle findStyle, + const ArtifactDesc& desc); + /// Find an artifact that predicate matches + static IArtifact* findArtifactByPredicate( + IArtifact* artifact, + FindStyle findStyle, + FindFunc func, + void* data); + /// Find by name + static IArtifact* findArtifactByName( + IArtifact* artifact, + FindStyle findStyle, + const char* name); + /// Find by desc exactly + static IArtifact* findArtifactByDesc( + IArtifact* artifact, + FindStyle findStyle, + const ArtifactDesc& desc); + + /// Creates an empty artifact for a type static ComPtr createArtifactForCompileTarget(SlangCompileTarget target); - /// Create an artifact + /// Create an artifact static ComPtr createArtifact(const ArtifactDesc& desc, const char* name); static ComPtr createArtifact(const ArtifactDesc& desc); - /// True if is significant + /// True if is significant static bool isSignificant(IArtifact* artifact); - /// True if is significant + /// True if is significant static bool isSignificant(const ArtifactDesc& desc); - /// Returns true if an artifact is 'significant'. - /// The data parameter is unused and just used to make work as FindFunc + /// Returns true if an artifact is 'significant'. + /// The data parameter is unused and just used to make work as FindFunc static bool isSignificant(IArtifact* artifact, void* data); - /// Find a significant artifact + /// Find a significant artifact static IArtifact* findSignificant(IArtifact* artifact); - /// Find the path/name associated with the artifact. - /// The path is *not* necessarily the path on the file system. The order of search is - /// * If the artifact has a name return that - /// * If the artifact has a IPathFileArtifactRepresentation (that isn't temporary) return it's path - /// * If not found return an empty slice + /// Find the path/name associated with the artifact. + /// The path is *not* necessarily the path on the file system. The order of search is + /// * If the artifact has a name return that + /// * If the artifact has a IPathFileArtifactRepresentation (that isn't temporary) return it's + /// path + /// * If not found return an empty slice static UnownedStringSlice findPath(IArtifact* artifact); - /// Find a name + /// Find a name static UnownedStringSlice findName(IArtifact* artifact); - /// Sometimes we have artifacts that don't specify a payload type - perhaps because they can be interpretted in different ways - /// This function uses the associated name and file representations to infer a extension. If none is found returns an empty slice. + /// Sometimes we have artifacts that don't specify a payload type - perhaps because they can be + /// interpretted in different ways This function uses the associated name and file + /// representations to infer a extension. If none is found returns an empty slice. static UnownedStringSlice inferExtension(IArtifact* artifact); - /// Given a desc and a basePath returns a suitable path for a entity of specified desc - static SlangResult calcPath(IArtifact* artifact, const UnownedStringSlice& basePath, StringBuilder& outPath); + /// Given a desc and a basePath returns a suitable path for a entity of specified desc + static SlangResult calcPath( + IArtifact* artifact, + const UnownedStringSlice& basePath, + StringBuilder& outPath); - /// Given a desc and a baseName works out the the output file name - static SlangResult calcName(IArtifact* artifact, const UnownedStringSlice& baseName, StringBuilder& outName); + /// Given a desc and a baseName works out the the output file name + static SlangResult calcName( + IArtifact* artifact, + const UnownedStringSlice& baseName, + StringBuilder& outName); - /// Convenience function that adds metadata to artifact. If metadata is nullptr nothing is added. + /// Convenience function that adds metadata to artifact. If metadata is nullptr nothing is + /// added. static void addAssociated(IArtifact* artifact, IArtifactPostEmitMetadata* metadata); - /// Convenience function that adds diagnostics to artifact. If diagnostics is nullptr nothing is added. + /// Convenience function that adds diagnostics to artifact. If diagnostics is nullptr nothing is + /// added. static void addAssociated(IArtifact* artifact, IArtifactDiagnostics* diagnostics); }; diff --git a/source/compiler-core/slang-artifact.h b/source/compiler-core/slang-artifact.h index d3784ca0a..46e8831ff 100644 --- a/source/compiler-core/slang-artifact.h +++ b/source/compiler-core/slang-artifact.h @@ -10,32 +10,39 @@ namespace Slang { -/* Simplest slice types. We can't use UnownedStringSlice etc, because they implement functionality in libraries, -and we want to use these types in headers. -If we wanted a C implementation it would be easy to use a macro to generate the functionality */ +/* Simplest slice types. We can't use UnownedStringSlice etc, because they implement functionality +in libraries, and we want to use these types in headers. If we wanted a C implementation it would be +easy to use a macro to generate the functionality */ -template +template struct Slice { const T* begin() const { return data; } const T* end() const { return data + count; } - const T& operator[](Index index) const { SLANG_ASSERT(index >= 0 && index < count); return data[index]; } + const T& operator[](Index index) const + { + SLANG_ASSERT(index >= 0 && index < count); + return data[index]; + } - Slice() :count(0), data(nullptr) {} - Slice(const T* inData, Count inCount) : - data(inData), - count(inCount) - {} + Slice() + : count(0), data(nullptr) + { + } + Slice(const T* inData, Count inCount) + : data(inData), count(inCount) + { + } const T* data; Count count; }; -template -SLANG_FORCE_INLINE Slice makeSlice(const T* inData, Count inCount) -{ - return Slice(inData, inCount); +template +SLANG_FORCE_INLINE Slice makeSlice(const T* inData, Count inCount) +{ + return Slice(inData, inCount); } struct CharSlice : public Slice @@ -43,13 +50,26 @@ struct CharSlice : public Slice typedef CharSlice ThisType; typedef Slice Super; - bool operator==(const ThisType& rhs) const { return count == rhs.count && (data == rhs.data || ::memcmp(data, rhs.data, count) == 0); } + bool operator==(const ThisType& rhs) const + { + return count == rhs.count && (data == rhs.data || ::memcmp(data, rhs.data, count) == 0); + } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - explicit CharSlice(const char* in) :Super(in, ::strlen(in)) {} - CharSlice(const char* in, Count inCount) :Super(in, inCount) {} - CharSlice() :Super(nullptr, 0) {} - explicit CharSlice(const String& s) :CharSlice(s.begin(), s.getLength()){}; + explicit CharSlice(const char* in) + : Super(in, ::strlen(in)) + { + } + CharSlice(const char* in, Count inCount) + : Super(in, inCount) + { + } + CharSlice() + : Super(nullptr, 0) + { + } + explicit CharSlice(const String& s) + : CharSlice(s.begin(), s.getLength()){}; }; static_assert(std::is_trivially_copyable_v); @@ -61,17 +81,28 @@ struct TerminatedCharSlice : public CharSlice SLANG_FORCE_INLINE bool operator==(const ThisType& rhs) const { return Super::operator==(rhs); } SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - /// Make convertable to char* - SLANG_FORCE_INLINE operator const char* () const { return data; } + /// Make convertable to char* + SLANG_FORCE_INLINE operator const char*() const { return data; } - explicit TerminatedCharSlice(const char* in) :Super(in) {} - TerminatedCharSlice(const char* in, Count inCount) :Super(in, inCount) { SLANG_ASSERT(in[inCount] == 0); } - TerminatedCharSlice() :Super("", 0) {} + explicit TerminatedCharSlice(const char* in) + : Super(in) + { + } + TerminatedCharSlice(const char* in, Count inCount) + : Super(in, inCount) + { + SLANG_ASSERT(in[inCount] == 0); + } + TerminatedCharSlice() + : Super("", 0) + { + } }; static_assert(std::is_trivially_copyable_v); -/* As a rule of thumb, if we can define some aspect in a hierarchy then we should do so at the highest level. -If some aspect can apply to multiple items identically we move that to a separate enum. +/* As a rule of thumb, if we can define some aspect in a hierarchy then we should do so at the +highest level. If some aspect can apply to multiple items identically we move that to a separate +enum. NOTE! New Kinds must be added at the end. Values can be deprecated, or disabled @@ -80,43 +111,43 @@ but never removed, without breaking binary compatability. Any change requires a change to SLANG_ARTIFACT_KIND */ enum class ArtifactKind : uint8_t -{ - Invalid, ///< Invalid - Base, ///< Base kind of all valid kinds - - None, ///< Doesn't contain anything - Unknown, ///< Unknown - - BinaryFormat, ///< A generic binary format. - - Container, ///< Container like types - Zip, ///< Zip container - RiffContainer, ///< Riff container - RiffLz4Container, ///< Riff container using Lz4 compression - RiffDeflateContainer, ///< Riff container using deflate compression - - Text, ///< Representation is text. Encoding is utf8, unless prefixed with 'encoding'. - - Source, ///< Source (Source type is in payload) - Assembly, ///< Assembly (Type is in payload) - HumanText, ///< Text for human consumption - - CompileBinary, ///< Kinds which are 'binary like' - can be executed, linked with and so forth. - - ObjectCode, ///< Object file - Library, ///< Library (collection of object code) - Executable, ///< Executable - SharedLibrary, ///< Shared library - can be dynamically linked - HostCallable, ///< Code can be executed directly on the host - - Instance, ///< Primary representation is an interface/class instance - - Json, ///< It's JSON +{ + Invalid, ///< Invalid + Base, ///< Base kind of all valid kinds + + None, ///< Doesn't contain anything + Unknown, ///< Unknown + + BinaryFormat, ///< A generic binary format. + + Container, ///< Container like types + Zip, ///< Zip container + RiffContainer, ///< Riff container + RiffLz4Container, ///< Riff container using Lz4 compression + RiffDeflateContainer, ///< Riff container using deflate compression + + Text, ///< Representation is text. Encoding is utf8, unless prefixed with 'encoding'. + + Source, ///< Source (Source type is in payload) + Assembly, ///< Assembly (Type is in payload) + HumanText, ///< Text for human consumption + + CompileBinary, ///< Kinds which are 'binary like' - can be executed, linked with and so forth. + + ObjectCode, ///< Object file + Library, ///< Library (collection of object code) + Executable, ///< Executable + SharedLibrary, ///< Shared library - can be dynamically linked + HostCallable, ///< Code can be executed directly on the host + + Instance, ///< Primary representation is an interface/class instance + + Json, ///< It's JSON CountOf, }; -/* Payload. +/* Payload. SlangIR and LLVMIR can be GPU or CPU orientated, so put in own category. @@ -128,69 +159,69 @@ Any change requires a change to SLANG_ARTIFACT_PAYLOAD */ enum class ArtifactPayload : uint8_t { - Invalid, ///< Is invalid - indicates some kind of problem - Base, ///< The base of the hierarchy - - None, ///< Doesn't have a payload - Unknown, ///< Unknown but probably valid - - Source, ///< Source code - - C, ///< C source - Cpp, ///< C++ source - HLSL, ///< HLSL source - GLSL, ///< GLSL source - CUDA, ///< CUDA source - Metal, ///< Metal source - Slang, ///< Slang source - WGSL, ///< WGSL source - - KernelLike, ///< GPU Kernel like - - DXIL, ///< DXIL - DXBC, ///< DXBC - SPIRV, ///< SPIR-V - PTX, ///< PTX. NOTE! PTX is a text format, but is handable to CUDA API. - MetalAIR, ///< Metal AIR - CuBin, ///< CUDA binary - WGSL_SPIRV, ///< SPIR-V derived via WebGPU shading language - - CPULike, ///< CPU code - - UnknownCPU, ///< CPU code for unknown/undetermined type - X86, ///< X86 - X86_64, ///< X86_64 - Aarch, ///< 32 bit arm - Aarch64, ///< Aarch64 - HostCPU, ///< HostCPU - UniversalCPU, ///< CPU code for multiple CPU types - - GeneralIR, ///< General purpose IR representation (IR) - - SlangIR, ///< Slang IR - LLVMIR, ///< LLVM IR - - AST, ///< Abstract syntax tree (AST) - - SlangAST, ///< Slang AST + Invalid, ///< Is invalid - indicates some kind of problem + Base, ///< The base of the hierarchy + + None, ///< Doesn't have a payload + Unknown, ///< Unknown but probably valid + + Source, ///< Source code + + C, ///< C source + Cpp, ///< C++ source + HLSL, ///< HLSL source + GLSL, ///< GLSL source + CUDA, ///< CUDA source + Metal, ///< Metal source + Slang, ///< Slang source + WGSL, ///< WGSL source + + KernelLike, ///< GPU Kernel like + + DXIL, ///< DXIL + DXBC, ///< DXBC + SPIRV, ///< SPIR-V + PTX, ///< PTX. NOTE! PTX is a text format, but is handable to CUDA API. + MetalAIR, ///< Metal AIR + CuBin, ///< CUDA binary + WGSL_SPIRV, ///< SPIR-V derived via WebGPU shading language + + CPULike, ///< CPU code + + UnknownCPU, ///< CPU code for unknown/undetermined type + X86, ///< X86 + X86_64, ///< X86_64 + Aarch, ///< 32 bit arm + Aarch64, ///< Aarch64 + HostCPU, ///< HostCPU + UniversalCPU, ///< CPU code for multiple CPU types + + GeneralIR, ///< General purpose IR representation (IR) + + SlangIR, ///< Slang IR + LLVMIR, ///< LLVM IR + + AST, ///< Abstract syntax tree (AST) + + SlangAST, ///< Slang AST CompileResults, ///< Payload is a collection of compilation results - Metadata, ///< Metadata + Metadata, ///< Metadata - DebugInfo, ///< Debugging information - Diagnostics, ///< Diagnostics information + DebugInfo, ///< Debugging information + Diagnostics, ///< Diagnostics information - Miscellaneous, ///< Category for miscellaneous payloads (like Log/Lock) + Miscellaneous, ///< Category for miscellaneous payloads (like Log/Lock) - Log, ///< Log file - Lock, ///< Typically some kind of 'lock' file. Contents is typically not important. + Log, ///< Log file + Lock, ///< Typically some kind of 'lock' file. Contents is typically not important. - PdbDebugInfo, ///< PDB debug info + PdbDebugInfo, ///< PDB debug info - SourceMap, ///< A source map + SourceMap, ///< A source map - PostEmitMetadata, ///< Metadata from post emit (binding information) + PostEmitMetadata, ///< Metadata from post emit (binding information) CountOf, }; @@ -205,18 +236,18 @@ Any change requires a change to SLANG_ARTIFACT_STYLE */ enum class ArtifactStyle : uint8_t { - Invalid, ///< Invalid style (indicating an error) + Invalid, ///< Invalid style (indicating an error) Base, - - None, ///< A style is not applicable - Unknown, ///< Unknown + None, ///< A style is not applicable + + Unknown, ///< Unknown - CodeLike, ///< For styles that are 'code like' such as 'kernel' or 'host'. + CodeLike, ///< For styles that are 'code like' such as 'kernel' or 'host'. - Kernel, ///< Compiled as `GPU kernel` style. - Host, ///< Compiled in `host` style - Obfuscated, ///< Holds something specific to obfuscation, such as an obfuscated source map + Kernel, ///< Compiled as `GPU kernel` style. + Host, ///< Compiled in `host` style + Obfuscated, ///< Holds something specific to obfuscation, such as an obfuscated source map CountOf, }; @@ -242,21 +273,35 @@ public: typedef ArtifactPayload Payload; typedef ArtifactStyle Style; typedef ArtifactFlags Flags; - + typedef uint32_t PackedBacking; enum class Packed : PackedBacking; - - /// Get in packed format + + /// Get in packed format inline Packed getPacked() const; - bool operator==(const ThisType& rhs) const { return kind == rhs.kind && payload == rhs.payload && style == rhs.style && flags == rhs.flags; } + bool operator==(const ThisType& rhs) const + { + return kind == rhs.kind && payload == rhs.payload && style == rhs.style && + flags == rhs.flags; + } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - /// Construct from the elements - static ThisType make(Kind inKind, Payload inPayload, Style inStyle = Style::Unknown, Flags flags = 0) { return ThisType{ inKind, inPayload, inStyle, flags }; } - static ThisType make(Kind inKind, Payload inPayload, const ThisType& base) { return ThisType{ inKind, inPayload, base.style, base.flags }; } + /// Construct from the elements + static ThisType make( + Kind inKind, + Payload inPayload, + Style inStyle = Style::Unknown, + Flags flags = 0) + { + return ThisType{inKind, inPayload, inStyle, flags}; + } + static ThisType make(Kind inKind, Payload inPayload, const ThisType& base) + { + return ThisType{inKind, inPayload, base.style, base.flags}; + } - /// Construct from the packed format + /// Construct from the packed format inline static ThisType make(Packed inPacked); Kind kind; @@ -269,14 +314,11 @@ public: inline ArtifactDesc::Packed ArtifactDesc::getPacked() const { typedef PackedBacking IntType; - return Packed((IntType(kind) << 24) | - (IntType(payload) << 16) | - (IntType(style) << 8) | - flags); + return Packed((IntType(kind) << 24) | (IntType(payload) << 16) | (IntType(style) << 8) | flags); } // -------------------------------------------------------------------------- -inline /* static */ArtifactDesc ArtifactDesc::make(Packed inPacked) +inline /* static */ ArtifactDesc ArtifactDesc::make(Packed inPacked) { const PackedBacking packed = PackedBacking(inPacked); @@ -295,43 +337,53 @@ class IPathArtifactRepresentation; class IArtifactRepresentation; -// Controls what items can be kept. +// Controls what items can be kept. enum class ArtifactKeep { - No, ///< Don't keep the item - Yes, ///< Yes keep the final item - All, ///< Keep the final item and any intermediataries + No, ///< Don't keep the item + Yes, ///< Yes keep the final item + All, ///< Keep the final item and any intermediataries }; /// True if can keep an intermediate item -SLANG_INLINE bool canKeepIntermediate(ArtifactKeep keep) { return keep == ArtifactKeep::All; } +SLANG_INLINE bool canKeepIntermediate(ArtifactKeep keep) +{ + return keep == ArtifactKeep::All; +} /// True if can keep -SLANG_INLINE bool canKeep(ArtifactKeep keep) { return Index(keep) >= Index(ArtifactKeep::Yes); } +SLANG_INLINE bool canKeep(ArtifactKeep keep) +{ + return Index(keep) >= Index(ArtifactKeep::Yes); +} /// Returns the keep type for an intermediate -SLANG_INLINE ArtifactKeep getIntermediateKeep(ArtifactKeep keep) { return (keep == ArtifactKeep::All) ? ArtifactKeep::All : ArtifactKeep::No; } +SLANG_INLINE ArtifactKeep getIntermediateKeep(ArtifactKeep keep) +{ + return (keep == ArtifactKeep::All) ? ArtifactKeep::All : ArtifactKeep::No; +} /* Forward define */ class IArtifactHandler; -/* The IArtifact interface is designed to represent some Artifact of compilation. It could be input to or output from a compilation. +/* The IArtifact interface is designed to represent some Artifact of compilation. It could be input +to or output from a compilation. An abstraction is desirable here, because depending on the compiler the artifact/s could be * A file on the file system * A blob * Multiple files -* Some other (perhaps multiple) in memory representations -* A name +* Some other (perhaps multiple) in memory representations +* A name -The artifact uses the Blob as the canonical in memory representation. +The artifact uses the Blob as the canonical in memory representation. Some downstream compilers require the artifact to be available as a file system file, or to produce artifacts that are files. The IArtifact type allows to abstract away this difference, including the -ability to turn an in memory representation into a temporary file on the file system. +ability to turn an in memory representation into a temporary file on the file system. -The mechanism also allows for 'Containers' which allow for Artifacts to contain other Artifacts (amongst other things). -Those artifacts may be other files. For example a downstream compilation that produces results as well as temporary -files could be a Container containing artifacts for +The mechanism also allows for 'Containers' which allow for Artifacts to contain other Artifacts +(amongst other things). Those artifacts may be other files. For example a downstream compilation +that produces results as well as temporary files could be a Container containing artifacts for * Diagnostics * Temporary files (of known and unknown types) @@ -344,20 +396,26 @@ There are several types of ways to associate data with an artifact: * An associated artifact * A child artifact -A `representation` has to wholly represent the artifact. That representation could be a blob, a file on the file system, -an in memory representation. There are two classes of `Representation` - ones that can be turned into blobs (and therefore -derive from IArtifactRepresentation) and ones that are in of themselves a representation (such as a blob or or ISlangSharedLibrary). +A `representation` has to wholly represent the artifact. That representation could be a blob, a file +on the file system, an in memory representation. There are two classes of `Representation` - ones +that can be turned into blobs (and therefore derive from IArtifactRepresentation) and ones that are +in of themselves a representation (such as a blob or or ISlangSharedLibrary). -`Associated artifacts` hold information that is associated with the artifact. It could be part -of the representation, or useful for the implementation of a representation. Could also be considered as a kind of side channel -to associate arbitrary data including temporary data with an artifact. +`Associated artifacts` hold information that is associated with the artifact. It could be part +of the representation, or useful for the implementation of a representation. Could also be +considered as a kind of side channel to associate arbitrary data including temporary data with an +artifact. A `child artifact` belongs to the artifact, within the hierarchy of artifacts. */ class IArtifact : public ICastable { public: - SLANG_COM_INTERFACE(0xf90acdb0, 0x9a4a, 0x414e, { 0x85, 0x45, 0x8b, 0x26, 0xc9, 0x2d, 0x94, 0x42 }) + SLANG_COM_INTERFACE( + 0xf90acdb0, + 0x9a4a, + 0x414e, + {0x85, 0x45, 0x8b, 0x26, 0xc9, 0x2d, 0x94, 0x42}) enum class ContainedKind { @@ -374,90 +432,100 @@ public: typedef ArtifactFlags Flags; typedef ArtifactKeep Keep; - - /// Get the Desc defining the contents of the artifact + + /// Get the Desc defining the contents of the artifact virtual SLANG_NO_THROW Desc SLANG_MCALL getDesc() = 0; - /// Returns true if the artifact in principal exists + /// Returns true if the artifact in principal exists virtual SLANG_NO_THROW bool SLANG_MCALL exists() = 0; - /// Load as a blob + /// Load as a blob virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadBlob(Keep keep, ISlangBlob** outBlob) = 0; - - /// Require artifact is available as a file. - /// NOTE! May need to serialize and write as a temporary file. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL requireFile(Keep keep, IOSFileArtifactRepresentation** outFileRep) = 0; - /// Load the artifact as a shared library - virtual SLANG_NO_THROW SlangResult SLANG_MCALL loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) = 0; + /// Require artifact is available as a file. + /// NOTE! May need to serialize and write as a temporary file. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + requireFile(Keep keep, IOSFileArtifactRepresentation** outFileRep) = 0; - /// Get the name of the artifact. This can be empty. + /// Load the artifact as a shared library + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary) = 0; + + /// Get the name of the artifact. This can be empty. virtual SLANG_NO_THROW const char* SLANG_MCALL getName() = 0; - /// Set the name associated with the artifact + /// Set the name associated with the artifact virtual SLANG_NO_THROW void SLANG_MCALL setName(const char* name) = 0; - /// Add associated artifacts with this artifact + /// Add associated artifacts with this artifact virtual SLANG_NO_THROW void SLANG_MCALL addAssociated(IArtifact* artifact) = 0; - /// Get the list of associated items + /// Get the list of associated items virtual SLANG_NO_THROW Slice SLANG_MCALL getAssociated() = 0; - - /// Add a representation + + /// Add a representation virtual SLANG_NO_THROW void SLANG_MCALL addRepresentation(ICastable* castable) = 0; - /// Add a representation that doesn't derive from IArtifactRepresentation + /// Add a representation that doesn't derive from IArtifactRepresentation virtual SLANG_NO_THROW void SLANG_MCALL addRepresentationUnknown(ISlangUnknown* rep) = 0; - /// Get all the representations + /// Get all the representations virtual SLANG_NO_THROW Slice SLANG_MCALL getRepresentations() = 0; - /// Given a typeGuid representing the desired type get or create the representation. - /// If found outCastable holds an entity that *must* be castable to typeGuid - /// Use the keep parameter to determine if the representation should be cached on the artifact/s or not. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation(const Guid& typeGuid, ArtifactKeep keep, ICastable** outCastable) = 0; - - /// Get the handler used for this artifact. If nullptr means the default handler will be used. + /// Given a typeGuid representing the desired type get or create the representation. + /// If found outCastable holds an entity that *must* be castable to typeGuid + /// Use the keep parameter to determine if the representation should be cached on the artifact/s + /// or not. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getOrCreateRepresentation(const Guid& typeGuid, ArtifactKeep keep, ICastable** outCastable) = 0; + + /// Get the handler used for this artifact. If nullptr means the default handler will be used. virtual SLANG_NO_THROW IArtifactHandler* SLANG_MCALL getHandler() = 0; - /// Set the handler associated with this artifact. Setting nullptr will use the default handler. + /// Set the handler associated with this artifact. Setting nullptr will use the default handler. virtual SLANG_NO_THROW void SLANG_MCALL setHandler(IArtifactHandler* handler) = 0; - /// Returns the result of expansion. Will return SLANG_E_UNINITIALIZED if expansion hasn't happened + /// Returns the result of expansion. Will return SLANG_E_UNINITIALIZED if expansion hasn't + /// happened virtual SLANG_NO_THROW SlangResult SLANG_MCALL getExpandChildrenResult() = 0; - /// Sets all of the children, will set the expansion state to SLANG_OK - virtual SLANG_NO_THROW void SLANG_MCALL setChildren(IArtifact*const* children, Count count) = 0; - /// Will be called implicitly on access to children + /// Sets all of the children, will set the expansion state to SLANG_OK + virtual SLANG_NO_THROW void SLANG_MCALL + setChildren(IArtifact* const* children, Count count) = 0; + /// Will be called implicitly on access to children virtual SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren() = 0; - /// Add the artifact to the list + /// Add the artifact to the list virtual SLANG_NO_THROW void SLANG_MCALL addChild(IArtifact* artifact) = 0; - /// Get the children, will only remain valid if no mutation of children list + /// Get the children, will only remain valid if no mutation of children list virtual SLANG_NO_THROW Slice SLANG_MCALL getChildren() = 0; - /// Find a represention from the specified list - virtual SLANG_NO_THROW void* SLANG_MCALL findRepresentation(ContainedKind kind, const Guid& guid) = 0; - /// Clear all of the contained kind + /// Find a represention from the specified list + virtual SLANG_NO_THROW void* SLANG_MCALL + findRepresentation(ContainedKind kind, const Guid& guid) = 0; + /// Clear all of the contained kind virtual SLANG_NO_THROW void SLANG_MCALL clear(ContainedKind kind) = 0; - /// Remove entry at index for the specified kind + /// Remove entry at index for the specified kind virtual SLANG_NO_THROW void SLANG_MCALL removeAt(ContainedKind kind, Index i) = 0; }; -template +template SLANG_FORCE_INLINE T* findRepresentation(IArtifact* artifact) { - return reinterpret_cast(artifact->findRepresentation(IArtifact::ContainedKind::Representation, T::getTypeGuid())); + return reinterpret_cast( + artifact->findRepresentation(IArtifact::ContainedKind::Representation, T::getTypeGuid())); } -template +template SLANG_FORCE_INLINE T* findAssociatedRepresentation(IArtifact* artifact) { - return reinterpret_cast(artifact->findRepresentation(IArtifact::ContainedKind::Associated, T::getTypeGuid())); + return reinterpret_cast( + artifact->findRepresentation(IArtifact::ContainedKind::Associated, T::getTypeGuid())); } -template +template SLANG_FORCE_INLINE T* findChildRepresentation(IArtifact* artifact) { - return reinterpret_cast(artifact->findRepresentation(IArtifact::ContainedKind::Children, T::getTypeGuid())); + return reinterpret_cast( + artifact->findRepresentation(IArtifact::ContainedKind::Children, T::getTypeGuid())); } -/* The IArtifactRepresentation interface represents a single representation that can be part of an artifact. It's special in so far -as +/* The IArtifactRepresentation interface represents a single representation that can be part of an +artifact. It's special in so far as * IArtifactRepresentation can be queried for it's underlying object class * Can determine if the representation exists (for example if it's on the file system) @@ -465,26 +533,35 @@ as */ class IArtifactRepresentation : public ICastable { - SLANG_COM_INTERFACE(0xa3790eb, 0x22b9, 0x430e, { 0xbf, 0xc6, 0x24, 0x6c, 0x5b, 0x5c, 0xcd, 0x0 }) + SLANG_COM_INTERFACE(0xa3790eb, 0x22b9, 0x430e, {0xbf, 0xc6, 0x24, 0x6c, 0x5b, 0x5c, 0xcd, 0x0}) - /// Create a representation of the specified typeGuid interface. - /// Calling castAs on the castable will return the specific type - /// Returns SLANG_E_NOT_IMPLEMENTED if an implementation doesn't implement - virtual SLANG_NO_THROW SlangResult SLANG_MCALL createRepresentation(const Guid& typeGuid, ICastable** outCastable) = 0; + /// Create a representation of the specified typeGuid interface. + /// Calling castAs on the castable will return the specific type + /// Returns SLANG_E_NOT_IMPLEMENTED if an implementation doesn't implement + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + createRepresentation(const Guid& typeGuid, ICastable** outCastable) = 0; - /// Returns true if this representation exists and is available for use. + /// Returns true if this representation exists and is available for use. virtual SLANG_NO_THROW bool SLANG_MCALL exists() = 0; }; /* Handler provides functionality external to the artifact */ class IArtifactHandler : public ICastable { - SLANG_COM_INTERFACE(0x6a646f57, 0xb3ac, 0x4c6a, { 0xb6, 0xf1, 0x33, 0xb6, 0xef, 0x60, 0xa6, 0xae }); + SLANG_COM_INTERFACE( + 0x6a646f57, + 0xb3ac, + 0x4c6a, + {0xb6, 0xf1, 0x33, 0xb6, 0xef, 0x60, 0xa6, 0xae}); - /// Given an artifact expands children + /// Given an artifact expands children virtual SLANG_NO_THROW SlangResult SLANG_MCALL expandChildren(IArtifact* container) = 0; - /// Given an artifact gets or creates a representation. - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation(IArtifact* artifact, const Guid& guid, ArtifactKeep keep, ICastable** outCastable) = 0; + /// Given an artifact gets or creates a representation. + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getOrCreateRepresentation( + IArtifact* artifact, + const Guid& guid, + ArtifactKeep keep, + ICastable** outCastable) = 0; }; } // namespace Slang diff --git a/source/compiler-core/slang-command-line-args.cpp b/source/compiler-core/slang-command-line-args.cpp index b69836030..451ea406c 100644 --- a/source/compiler-core/slang-command-line-args.cpp +++ b/source/compiler-core/slang-command-line-args.cpp @@ -6,9 +6,10 @@ #include "../core/slang-type-text-util.h" #include "slang-core-diagnostics.h" -namespace Slang { +namespace Slang +{ -void CommandLineArgs::setArgs(const char*const* args, size_t argCount) +void CommandLineArgs::setArgs(const char* const* args, size_t argCount) { m_args.clear(); @@ -17,7 +18,7 @@ void CommandLineArgs::setArgs(const char*const* args, size_t argCount) const SourceLoc startLoc = sourceManager->getNextRangeStart(); StringBuilder buf; - + auto escapeHandler = Process::getEscapeHandler(); for (size_t i = 0; i < argCount; ++i) @@ -39,14 +40,16 @@ void CommandLineArgs::setArgs(const char*const* args, size_t argCount) buf << " "; } - SourceFile* sourceFile = sourceManager->createSourceFileWithString(PathInfo::makeUnknown(), buf.produceString()); - SourceView* sourceView = sourceManager->createSourceView(sourceFile, nullptr, SourceLoc::fromRaw(0)); + SourceFile* sourceFile = + sourceManager->createSourceFileWithString(PathInfo::makeUnknown(), buf.produceString()); + SourceView* sourceView = + sourceManager->createSourceView(sourceFile, nullptr, SourceLoc::fromRaw(0)); SLANG_UNUSED(sourceView); SLANG_ASSERT(sourceView->getRange().begin == startLoc); } -bool CommandLineArgs::hasArgs(const char*const* args, Index count) const +bool CommandLineArgs::hasArgs(const char* const* args, Index count) const { if (m_args.getCount() != count) { @@ -164,12 +167,16 @@ Index DownstreamArgs::addName(const String& name) if (index < 0) { index = m_entries.getCount(); - m_entries.add(Entry{name, CommandLineArgs(m_context) }); + m_entries.add(Entry{name, CommandLineArgs(m_context)}); } return index; } -Index DownstreamArgs::_findOrAddName(SourceLoc loc, const UnownedStringSlice& name, Flags flags, DiagnosticSink* sink) +Index DownstreamArgs::_findOrAddName( + SourceLoc loc, + const UnownedStringSlice& name, + Flags flags, + DiagnosticSink* sink) { if (name.getLength() <= 0) { @@ -225,7 +232,10 @@ const CommandLineArgs& DownstreamArgs::getArgsByName(const char* name) const return m_entries[index].args; } -SlangResult DownstreamArgs::stripDownstreamArgs(CommandLineArgs& ioArgs, Flags flags, DiagnosticSink* sink) +SlangResult DownstreamArgs::stripDownstreamArgs( + CommandLineArgs& ioArgs, + Flags flags, + DiagnosticSink* sink) { CommandLineReader reader(&ioArgs, sink); @@ -237,7 +247,8 @@ SlangResult DownstreamArgs::stripDownstreamArgs(CommandLineArgs& ioArgs, Flags f { if (arg.value.endsWith("...")) { - const UnownedStringSlice name = arg.value.getUnownedSlice().subString(2, arg.value.getLength() - 5); + const UnownedStringSlice name = + arg.value.getUnownedSlice().subString(2, arg.value.getLength() - 5); const Index nameIndex = _findOrAddName(arg.loc, name, flags, sink); if (nameIndex < 0) { @@ -283,7 +294,9 @@ SlangResult DownstreamArgs::stripDownstreamArgs(CommandLineArgs& ioArgs, Flags f CommandLineArgs& args = getArgsAt(nameIndex); // Copy the values in the range - args.m_args.addRange(ioArgs.m_args.getBuffer() + startIndex + 1, index - (startIndex + 1)); + args.m_args.addRange( + ioArgs.m_args.getBuffer() + startIndex + 1, + index - (startIndex + 1)); // If we aren't at the end, we must be pointing to -X., so skip that index += Index(index < count); diff --git a/source/compiler-core/slang-command-line-args.h b/source/compiler-core/slang-command-line-args.h index 0c11a3c46..388847f5c 100644 --- a/source/compiler-core/slang-command-line-args.h +++ b/source/compiler-core/slang-command-line-args.h @@ -5,33 +5,34 @@ // the name of types, variables, etc. in the AST. #include "../core/slang-basic.h" - -#include "slang-source-loc.h" #include "slang-diagnostic-sink.h" +#include "slang-source-loc.h" -namespace Slang { +namespace Slang +{ struct CommandLineArg { - String value; ///< The value of the arg - SourceLoc loc; ///< The location of the arg + String value; ///< The value of the arg + SourceLoc loc; ///< The location of the arg }; -/* This type ends up being really just a container for the sourceManager that has the CommandLine specific SourceLocs. -That it would perhaps be better to just have SourceManager derive from RefObject, and then we could remove this -type. */ +/* This type ends up being really just a container for the sourceManager that has the CommandLine +specific SourceLocs. That it would perhaps be better to just have SourceManager derive from +RefObject, and then we could remove this type. */ class CommandLineContext : public RefObject { -public: - /// Get the source manager +public: + /// Get the source manager SourceManager* getSourceManager() { return &m_sourceManager; } CommandLineContext(ISlangFileSystemExt* fileSystemExt = nullptr) { m_sourceManager.initialize(nullptr, fileSystemExt); // Make range start from high value, so can be differentiated from other uses - // That this doesn't not assume exclusive use of this range - just that in normal use scenarios - // there is no confusion, and using the wrong source manager, will typically report nothing is found. + // That this doesn't not assume exclusive use of this range - just that in normal use + // scenarios there is no confusion, and using the wrong source manager, will typically + // report nothing is found. m_sourceManager.allocateSourceRange(~(~SourceLoc::RawValue(0) >> 1)); } @@ -49,26 +50,26 @@ struct CommandLineArgs const Arg* begin() const { return m_args.begin(); } const Arg* end() const { return m_args.end(); } - /// NOTE! Should NOT include the executable name - void setArgs(const char*const* args, size_t argCount); + /// NOTE! Should NOT include the executable name + void setArgs(const char* const* args, size_t argCount); - /// True if has args in same order - bool hasArgs(const char*const* args, Index count) const; + /// True if has args in same order + bool hasArgs(const char* const* args, Index count) const; - /// Add an arg + /// Add an arg void add(const Arg& arg) { m_args.add(arg); } - /// Ctor with a context - CommandLineArgs(CommandLineContext* context): - m_context(context) + /// Ctor with a context + CommandLineArgs(CommandLineContext* context) + : m_context(context) { } - /// Default Ctor + /// Default Ctor CommandLineArgs() {} - //String m_executablePath; ///< Can be optionally be set - List m_args; ///< The args - RefPtr m_context; ///< The context, which mainly has source manager + // String m_executablePath; ///< Can be optionally be set + List m_args; ///< The args + RefPtr m_context; ///< The context, which mainly has source manager String serialize(); void deserialize(String content); @@ -76,45 +77,83 @@ struct CommandLineArgs struct CommandLineReader { - /// Peek the current location - SourceLoc peekLoc() const { return m_index < m_args->getArgCount() ? (*m_args)[m_index].loc : SourceLoc(); } - /// Peek the current arg - const CommandLineArg& peekArg() const { SLANG_ASSERT(hasArg()); return (*m_args)[m_index]; } + /// Peek the current location + SourceLoc peekLoc() const + { + return m_index < m_args->getArgCount() ? (*m_args)[m_index].loc : SourceLoc(); + } + /// Peek the current arg + const CommandLineArg& peekArg() const + { + SLANG_ASSERT(hasArg()); + return (*m_args)[m_index]; + } - /// Peek the string value at that position - const String& peekValue() const { SLANG_ASSERT(hasArg()); return (*m_args)[m_index].value; } + /// Peek the string value at that position + const String& peekValue() const + { + SLANG_ASSERT(hasArg()); + return (*m_args)[m_index].value; + } - /// Get the arg and advance - CommandLineArg getArgAndAdvance() { CommandLineArg arg(peekArg()); advance(); return arg; } + /// Get the arg and advance + CommandLineArg getArgAndAdvance() + { + CommandLineArg arg(peekArg()); + advance(); + return arg; + } - const String& getValueAndAdvance() { const String& value = peekValue(); advance(); return value; } + const String& getValueAndAdvance() + { + const String& value = peekValue(); + advance(); + return value; + } - /// True if at end + /// True if at end bool atEnd() const { return m_index >= m_args->getArgCount(); } - /// True if has a current arg + /// True if has a current arg bool hasArg() const { return !atEnd(); } - /// Advance to next arg - void advance() { SLANG_ASSERT(m_index < m_args->getArgCount()); m_index++; } - /// Removes arg at current position - void removeArg() { SLANG_ASSERT(hasArg()); m_args->m_args.removeAt(m_index); } + /// Advance to next arg + void advance() + { + SLANG_ASSERT(m_index < m_args->getArgCount()); + m_index++; + } + /// Removes arg at current position + void removeArg() + { + SLANG_ASSERT(hasArg()); + m_args->m_args.removeAt(m_index); + } - /// Get the value from the arg previous to the current position. Will assert if there isn't one. - String getPreviousValue() const; + /// Get the value from the arg previous to the current position. Will assert if there isn't one. + String getPreviousValue() const; - /// If there is an arg outArg is set and advanced - /// Note, this *assumes* the previous arg is the option that initated this + /// If there is an arg outArg is set and advanced + /// Note, this *assumes* the previous arg is the option that initated this SlangResult expectArg(String& outArg); SlangResult expectArg(CommandLineArg& outArg); - /// Get the current index + /// Get the current index Index getIndex() const { return m_index; } - /// Set the current index - void setIndex(Index index) { SLANG_ASSERT(index >= 0 && index <= m_args->getArgCount()); m_index = index; } + /// Set the current index + void setIndex(Index index) + { + SLANG_ASSERT(index >= 0 && index <= m_args->getArgCount()); + m_index = index; + } - void init(CommandLineArgs* args, DiagnosticSink* sink) { m_args = args; m_sink = sink; m_index = 0; } + void init(CommandLineArgs* args, DiagnosticSink* sink) + { + m_args = args; + m_sink = sink; + m_index = 0; + } - /// Set up reader with args + /// Set up reader with args CommandLineReader(CommandLineArgs* args, DiagnosticSink* sink) { init(args, sink); } CommandLineReader() = default; @@ -136,39 +175,48 @@ struct DownstreamArgs struct Entry { - String name; ///< The name of the 'tool' that these args are associated with - CommandLineArgs args; ///< The args to be passed to the tool + String name; ///< The name of the 'tool' that these args are associated with + CommandLineArgs args; ///< The args to be passed to the tool }; - /// Add a name, returns the index + /// Add a name, returns the index Index addName(const String& name); - /// Find the index of a name. Returns < 0 if not found. - Index findName(const String& name) const { return m_entries.findFirstIndex([&](const Entry& entry) -> bool { return entry.name == name; }); } + /// Find the index of a name. Returns < 0 if not found. + Index findName(const String& name) const + { + return m_entries.findFirstIndex( + [&](const Entry& entry) -> bool { return entry.name == name; }); + } - /// Get the args at the nameIndex + /// Get the args at the nameIndex CommandLineArgs& getArgsAt(Index nameIndex) { return m_entries[nameIndex].args; } - /// Get args by name - will assert if name isn't found + /// Get args by name - will assert if name isn't found CommandLineArgs& getArgsByName(const char* name); const CommandLineArgs& getArgsByName(const char* name) const; - /// Looks for '-X' expressions, removing them from ioArgs and putting in appropriate args + /// Looks for '-X' expressions, removing them from ioArgs and putting in appropriate args SlangResult stripDownstreamArgs(CommandLineArgs& ioArgs, Flags flags, DiagnosticSink* sink); - /// Get the context used + /// Get the context used CommandLineContext* getContext() const { return m_context; } - /// Ctor + /// Ctor DownstreamArgs(CommandLineContext* context); - /// Default ctor - for convenience, should really use with context normally + /// Default ctor - for convenience, should really use with context normally DownstreamArgs() {} - List m_entries; ///< All of the entries + List m_entries; ///< All of the entries protected: - Index _findOrAddName(SourceLoc loc, const UnownedStringSlice& name, Flags flags, DiagnosticSink* sink); - - RefPtr m_context; ///< The context that is being used (primarily for loc tracking) across all entries/args + Index _findOrAddName( + SourceLoc loc, + const UnownedStringSlice& name, + Flags flags, + DiagnosticSink* sink); + + RefPtr m_context; ///< The context that is being used (primarily for loc + ///< tracking) across all entries/args }; diff --git a/source/compiler-core/slang-core-diagnostics.cpp b/source/compiler-core/slang-core-diagnostics.cpp index 7aa6c5c14..4fbae6873 100644 --- a/source/compiler-core/slang-core-diagnostics.cpp +++ b/source/compiler-core/slang-core-diagnostics.cpp @@ -1,18 +1,19 @@ // slang-core-diagnostics.cpp #include "slang-core-diagnostics.h" -namespace Slang { +namespace Slang +{ namespace MiscDiagnostics { -#define DIAGNOSTIC(id, severity, name, messageFormat) const DiagnosticInfo name = { id, Severity::severity, #name, messageFormat }; +#define DIAGNOSTIC(id, severity, name, messageFormat) \ + const DiagnosticInfo name = {id, Severity::severity, #name, messageFormat}; #include "slang-misc-diagnostic-defs.h" #undef DIAGNOSTIC -} +} // namespace MiscDiagnostics -static const DiagnosticInfo* const kMiscDiagnostics[] = -{ -#define DIAGNOSTIC(id, severity, name, messageFormat) &MiscDiagnostics::name, +static const DiagnosticInfo* const kMiscDiagnostics[] = { +#define DIAGNOSTIC(id, severity, name, messageFormat) &MiscDiagnostics::name, #include "slang-misc-diagnostic-defs.h" #undef DIAGNOSTIC }; @@ -20,14 +21,14 @@ static const DiagnosticInfo* const kMiscDiagnostics[] = namespace LexerDiagnostics { -#define DIAGNOSTIC(id, severity, name, messageFormat) const DiagnosticInfo name = { id, Severity::severity, #name, messageFormat }; +#define DIAGNOSTIC(id, severity, name, messageFormat) \ + const DiagnosticInfo name = {id, Severity::severity, #name, messageFormat}; #include "slang-lexer-diagnostic-defs.h" #undef DIAGNOSTIC -} +} // namespace LexerDiagnostics -static const DiagnosticInfo* const kLexerDiagnostics[] = -{ -#define DIAGNOSTIC(id, severity, name, messageFormat) &LexerDiagnostics::name, +static const DiagnosticInfo* const kLexerDiagnostics[] = { +#define DIAGNOSTIC(id, severity, name, messageFormat) &LexerDiagnostics::name, #include "slang-lexer-diagnostic-defs.h" #undef DIAGNOSTIC }; diff --git a/source/compiler-core/slang-core-diagnostics.h b/source/compiler-core/slang-core-diagnostics.h index fd1906fae..815a042c0 100644 --- a/source/compiler-core/slang-core-diagnostics.h +++ b/source/compiler-core/slang-core-diagnostics.h @@ -3,11 +3,9 @@ #include "../core/slang-basic.h" #include "../core/slang-writer.h" - -#include "slang-source-loc.h" #include "slang-diagnostic-sink.h" +#include "slang-source-loc.h" #include "slang-token.h" - #include "slang.h" namespace Slang @@ -19,14 +17,14 @@ namespace MiscDiagnostics { #define DIAGNOSTIC(id, severity, name, messageFormat) extern const DiagnosticInfo name; #include "slang-misc-diagnostic-defs.h" -} +} // namespace MiscDiagnostics namespace LexerDiagnostics { #define DIAGNOSTIC(id, severity, name, messageFormat) extern const DiagnosticInfo name; #include "slang-lexer-diagnostic-defs.h" -} +} // namespace LexerDiagnostics -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-diagnostic-sink.cpp b/source/compiler-core/slang-diagnostic-sink.cpp index a4cbce22f..537892f08 100644 --- a/source/compiler-core/slang-diagnostic-sink.cpp +++ b/source/compiler-core/slang-diagnostic-sink.cpp @@ -1,16 +1,16 @@ // slang-diagnostic-sink.cpp #include "slang-diagnostic-sink.h" -#include "slang-name.h" -#include "slang-core-diagnostics.h" -#include "slang-name-convention-util.h" - -#include "../core/slang-memory-arena.h" +#include "../core/slang-char-util.h" #include "../core/slang-dictionary.h" +#include "../core/slang-memory-arena.h" #include "../core/slang-string-util.h" -#include "../core/slang-char-util.h" +#include "slang-core-diagnostics.h" +#include "slang-name-convention-util.h" +#include "slang-name.h" -namespace Slang { +namespace Slang +{ void printDiagnosticArg(StringBuilder& sb, char const* str) { @@ -75,10 +75,14 @@ SourceLoc getDiagnosticPos(Token const& token) } // Take the format string for a diagnostic message, along with its arguments, and turn it into a -static void formatDiagnosticMessage(StringBuilder& sb, char const* format, int argCount, DiagnosticArg const* args) +static void formatDiagnosticMessage( + StringBuilder& sb, + char const* format, + int argCount, + DiagnosticArg const* args) { char const* spanBegin = format; - for(;;) + for (;;) { char const* spanEnd = spanBegin; while (int c = *spanEnd) @@ -97,21 +101,28 @@ static void formatDiagnosticMessage(StringBuilder& sb, char const* format, int a int d = *spanEnd++; switch (d) { - // A double dollar sign `$$` is used to emit a single `$` - case '$': - sb.append('$'); - break; + // A double dollar sign `$$` is used to emit a single `$` + case '$': sb.append('$'); break; // A single digit means to emit the corresponding argument. // TODO: support more than 10 arguments, and add options // to control formatting, etc. - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { int index = d - '0'; if (index >= argCount) { - // TODO(tfoley): figure out what a good policy will be for "panic" situations like this + // TODO(tfoley): figure out what a good policy will be for "panic" situations + // like this SLANG_INVALID_OPERATION("too few arguments for diagnostic message"); } else @@ -122,16 +133,18 @@ static void formatDiagnosticMessage(StringBuilder& sb, char const* format, int a } break; - default: - SLANG_INVALID_OPERATION("invalid diagnostic message format"); - break; + default: SLANG_INVALID_OPERATION("invalid diagnostic message format"); break; } spanBegin = spanEnd; } } -static void formatDiagnostic(const HumaneSourceLoc& humaneLoc, Diagnostic const& diagnostic, DiagnosticSink::Flags flags, StringBuilder& outBuilder) +static void formatDiagnostic( + const HumaneSourceLoc& humaneLoc, + Diagnostic const& diagnostic, + DiagnosticSink::Flags flags, + StringBuilder& outBuilder) { if (flags & DiagnosticSink::Flag::HumaneLoc) { @@ -161,7 +174,7 @@ static void formatDiagnostic(const HumaneSourceLoc& humaneLoc, Diagnostic const& static void _replaceTabWithSpaces(const UnownedStringSlice& slice, Int tabSize, StringBuilder& out) { const char* start = slice.begin(); - const char*const end = slice.end(); + const char* const end = slice.end(); const Index startLength = out.getLength(); @@ -211,12 +224,14 @@ static void _replaceTabWithSpaces(const UnownedStringSlice& slice, Int tabSize, // Given multi-line text, and a position within the text (as a pointer into the memory of text) // extract the line that contains pos -static UnownedStringSlice _extractLineContainingPosition(const UnownedStringSlice& text, const char* pos) +static UnownedStringSlice _extractLineContainingPosition( + const UnownedStringSlice& text, + const char* pos) { SLANG_ASSERT(text.isMemoryContained(pos)); - const char*const contentStart = text.begin(); - const char*const contentEnd = text.end(); + const char* const contentStart = text.begin(); + const char* const contentEnd = text.end(); // We want to determine the start of the line, and the end of the line const char* start = pos; @@ -251,7 +266,11 @@ static void _reduceLength(Index startIndex, const UnownedStringSlice& prefix, St ioBuf = buf; } -static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sourceView, SourceLoc sourceLoc, StringBuilder& sb) +static void _sourceLocationNoteDiagnostic( + DiagnosticSink* sink, + SourceView* sourceView, + SourceLoc sourceLoc, + StringBuilder& sb) { SourceFile* sourceFile = sourceView->getSourceFile(); if (!sourceFile) @@ -262,8 +281,9 @@ static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sour UnownedStringSlice content = sourceFile->getContent(); // Make sure the offset is within content. - // This is important because it's possible to have a 'SourceFile' that doesn't contain any content - // (for example when reconstructed via serialization with just line offsets, the actual source text 'content' isn't available). + // This is important because it's possible to have a 'SourceFile' that doesn't contain any + // content (for example when reconstructed via serialization with just line offsets, the actual + // source text 'content' isn't available). const int offset = sourceView->getRange().getOffset(sourceLoc); if (offset < 0 || offset >= content.getLength()) { @@ -271,7 +291,7 @@ static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sour } // Work out the position of the SourceLoc in the source - const char*const pos = content.begin() + offset; + const char* const pos = content.begin() + offset; UnownedStringSlice line = _extractLineContainingPosition(content, pos); @@ -287,7 +307,7 @@ static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sour // First work out the sourceLine _replaceTabWithSpaces(line, tabSize, sourceLine); - + // Now the caretLine which appears underneath the sourceLine { // Produce the text up to the caret position (at pos), taking into account tabs @@ -321,9 +341,9 @@ static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sour const UnownedStringSlice spaces = UnownedStringSlice::fromLiteral(" "); SLANG_ASSERT(ellipsis.getLength() == spaces.getLength()); - // We use the caretLine length if we have a lexer, because it will have underscores such that it's end is the end of - // the item at issue. - // If we don't have the lexer, we guesstimate using 1/4 of the maximum length + // We use the caretLine length if we have a lexer, because it will have underscores such + // that it's end is the end of the item at issue. If we don't have the lexer, we + // guesstimate using 1/4 of the maximum length const Index endIndex = lexer ? caretLine.getLength() : (caretIndex + (maxLength / 4)); if (endIndex > maxLength) @@ -344,9 +364,8 @@ static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sour } } - // We could have handling here for if the line is too long, that we surround the important section - // will ellipsis for example. - // For now we just output. + // We could have handling here for if the line is too long, that we surround the important + // section will ellipsis for example. For now we just output. sb << sourceLine << "\n"; sb << caretLine << "\n"; @@ -354,7 +373,10 @@ static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sour // Output the length of the token at `sourceLoc`. This is used by language server. static void _tokenLengthNoteDiagnostic( - DiagnosticSink* sink, SourceView* sourceView, SourceLoc sourceLoc, StringBuilder& sb) + DiagnosticSink* sink, + SourceView* sourceView, + SourceLoc sourceLoc, + StringBuilder& sb) { SourceFile* sourceFile = sourceView->getSourceFile(); if (!sourceFile) @@ -394,10 +416,7 @@ static void _tokenLengthNoteDiagnostic( } } -static void formatDiagnostic( - DiagnosticSink* sink, - Diagnostic const& diagnostic, - StringBuilder& sb) +static void formatDiagnostic(DiagnosticSink* sink, Diagnostic const& diagnostic, StringBuilder& sb) { auto sourceManager = sink->getSourceManager(); @@ -413,15 +432,19 @@ static void formatDiagnostic( humaneLoc = sourceView->getHumaneLoc(sourceLoc); } } - + formatDiagnostic(humaneLoc, diagnostic, sink->getFlags(), sb); { SourceView* currentView = sourceView; - while (currentView && currentView->getInitiatingSourceLoc().isValid() && currentView->getSourceFile()->getPathInfo().type == PathInfo::Type::TokenPaste) + while (currentView && currentView->getInitiatingSourceLoc().isValid() && + currentView->getSourceFile()->getPathInfo().type == PathInfo::Type::TokenPaste) { - SourceView* initiatingView = sourceManager ? sourceManager->findSourceView(currentView->getInitiatingSourceLoc()) : nullptr; + SourceView* initiatingView = + sourceManager + ? sourceManager->findSourceView(currentView->getInitiatingSourceLoc()) + : nullptr; if (initiatingView == nullptr) { break; @@ -441,8 +464,10 @@ static void formatDiagnostic( initiationDiagnostic.severity = diagnosticInfo.severity; // TODO(JS): - // Not 100% clear what the best sourceLoc type is most useful here - we will go with default for now - HumaneSourceLoc pasteHumaneLoc = initiatingView->getHumaneLoc(sourceView->getInitiatingSourceLoc()); + // Not 100% clear what the best sourceLoc type is most useful here - we will go + // with default for now + HumaneSourceLoc pasteHumaneLoc = + initiatingView->getHumaneLoc(sourceView->getInitiatingSourceLoc()); // Okay we should output where the token paste took place formatDiagnostic(pasteHumaneLoc, initiationDiagnostic, sink->getFlags(), sb); @@ -459,7 +484,8 @@ static void formatDiagnostic( _tokenLengthNoteDiagnostic(sink, sourceView, sourceLoc, sb); } - if (sourceView && sink->isFlagSet(DiagnosticSink::Flag::SourceLocationLine) && diagnostic.loc.isValid()) + if (sourceView && sink->isFlagSet(DiagnosticSink::Flag::SourceLocationLine) && + diagnostic.loc.isValid()) { _sourceLocationNoteDiagnostic(sink, sourceView, sourceLoc, sb); } @@ -473,9 +499,8 @@ static void formatDiagnostic( // Only output if it's actually different if (actualHumaneLoc.pathInfo.foundPath != humaneLoc.pathInfo.foundPath || - actualHumaneLoc.line != humaneLoc.line || - actualHumaneLoc.column != humaneLoc.column) - { + actualHumaneLoc.line != humaneLoc.line || actualHumaneLoc.column != humaneLoc.column) + { formatDiagnostic(actualHumaneLoc, diagnostic, sink->getFlags(), sb); } } @@ -533,7 +558,8 @@ SlangResult DiagnosticSink::getBlobIfNeeded(ISlangBlob** outBlob) { // If the client doesn't want an output blob, there is nothing to do. // - if (!outBlob) return SLANG_OK; + if (!outBlob) + return SLANG_OK; // For outputBuffer to be valid and hold diagnostics, writer must not be set SLANG_ASSERT(writer == nullptr); @@ -550,7 +576,9 @@ SlangResult DiagnosticSink::getBlobIfNeeded(ISlangBlob** outBlob) return SLANG_OK; } -bool DiagnosticSink::diagnoseImpl(DiagnosticInfo const& info, const UnownedStringSlice& formattedMessage) +bool DiagnosticSink::diagnoseImpl( + DiagnosticInfo const& info, + const UnownedStringSlice& formattedMessage) { if (info.severity >= Severity::Error) { @@ -600,7 +628,11 @@ Severity DiagnosticSink::getEffectiveMessageSeverity(DiagnosticInfo const& info) return effectiveSeverity; } -bool DiagnosticSink::diagnoseImpl(SourceLoc const& pos, DiagnosticInfo info, int argCount, DiagnosticArg const* args) +bool DiagnosticSink::diagnoseImpl( + SourceLoc const& pos, + DiagnosticInfo info, + int argCount, + DiagnosticArg const* args) { // Override the severity in the 'info' structure to pass it further into formatDiagnostics info.severity = getEffectiveMessageSeverity(info); @@ -626,16 +658,12 @@ bool DiagnosticSink::diagnoseImpl(SourceLoc const& pos, DiagnosticInfo info, int return diagnoseImpl(info, messageBuilder.getUnownedSlice()); } -void DiagnosticSink::diagnoseRaw( - Severity severity, - char const* message) +void DiagnosticSink::diagnoseRaw(Severity severity, char const* message) { return diagnoseRaw(severity, UnownedStringSlice(message)); } -void DiagnosticSink::diagnoseRaw( - Severity severity, - const UnownedStringSlice& message) +void DiagnosticSink::diagnoseRaw(Severity severity, const UnownedStringSlice& message) { if (severity >= Severity::Error) { @@ -643,7 +671,7 @@ void DiagnosticSink::diagnoseRaw( } // Did the client supply a callback for us to use? - if(writer) + if (writer) { // If so, pass the error string along to them. writer->write(message.begin(), message.getLength()); @@ -667,7 +695,10 @@ void DiagnosticSink::diagnoseRaw( } } -void DiagnosticSink::overrideDiagnosticSeverity(int diagnosticId, Severity overrideSeverity, const DiagnosticInfo* info) +void DiagnosticSink::overrideDiagnosticSeverity( + int diagnosticId, + Severity overrideSeverity, + const DiagnosticInfo* info) { if (info) { @@ -685,7 +716,8 @@ void DiagnosticSink::overrideDiagnosticSeverity(int diagnosticId, Severity overr m_severityOverrides[diagnosticId] = overrideSeverity; } -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DiagnosticLookup !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DiagnosticLookup + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ Index DiagnosticsLookup::_findDiagnosticIndexByExactName(const UnownedStringSlice& slice) const { @@ -715,7 +747,8 @@ const DiagnosticInfo* DiagnosticsLookup::getDiagnosticById(Int id) const return indexPtr ? m_diagnostics[*indexPtr] : nullptr; } -const DiagnosticInfo* DiagnosticsLookup::findDiagnosticByExactName(const UnownedStringSlice& slice) const +const DiagnosticInfo* DiagnosticsLookup::findDiagnosticByExactName( + const UnownedStringSlice& slice) const { const Index* indexPtr = m_nameMap.tryGetValue(slice); return indexPtr ? m_diagnostics[*indexPtr] : nullptr; @@ -726,9 +759,9 @@ const DiagnosticInfo* DiagnosticsLookup::findDiagnosticByName(const UnownedStrin const auto convention = NameConventionUtil::inferConventionFromText(slice); switch (convention) { - case NameConvention::Invalid: return nullptr; - case NameConvention::LowerCamel: return findDiagnosticByExactName(slice); - default: break; + case NameConvention::Invalid: return nullptr; + case NameConvention::LowerCamel: return findDiagnosticByExactName(slice); + default: break; } StringBuilder buf; @@ -747,11 +780,11 @@ Index DiagnosticsLookup::add(const DiagnosticInfo* info) _addName(info->name, diagnosticIndex); m_idMap.addIfNotExists(info->id, diagnosticIndex); - + return diagnosticIndex; } -void DiagnosticsLookup::add(const DiagnosticInfo*const* infos, Index infosCount) +void DiagnosticsLookup::add(const DiagnosticInfo* const* infos, Index infosCount) { for (Index i = 0; i < infosCount; ++i) { @@ -759,19 +792,21 @@ void DiagnosticsLookup::add(const DiagnosticInfo*const* infos, Index infosCount) } } -DiagnosticsLookup::DiagnosticsLookup(): - m_arena(kArenaInitialSize) +DiagnosticsLookup::DiagnosticsLookup() + : m_arena(kArenaInitialSize) { } -DiagnosticsLookup::DiagnosticsLookup(const DiagnosticInfo*const* diagnostics, Index diagnosticsCount) : - m_arena(kArenaInitialSize) +DiagnosticsLookup::DiagnosticsLookup( + const DiagnosticInfo* const* diagnostics, + Index diagnosticsCount) + : m_arena(kArenaInitialSize) { // TODO: We should eventually have a more formal system for associating individual // diagnostics, or groups of diagnostics, with user-exposed names for use when // enabling/disabling warnings (or turning warnings into errors, etc.). // - // For now we build a map from diagnostic name to it's entry. + // For now we build a map from diagnostic name to it's entry. add(diagnostics, diagnosticsCount); } diff --git a/source/compiler-core/slang-diagnostic-sink.h b/source/compiler-core/slang-diagnostic-sink.h index 38a31752f..9a4116855 100644 --- a/source/compiler-core/slang-diagnostic-sink.h +++ b/source/compiler-core/slang-diagnostic-sink.h @@ -2,12 +2,10 @@ #define SLANG_DIAGNOSTIC_SINK_H #include "../core/slang-basic.h" -#include "../core/slang-writer.h" #include "../core/slang-memory-arena.h" - +#include "../core/slang-writer.h" #include "slang-source-loc.h" #include "slang-token.h" - #include "slang.h" namespace Slang @@ -24,25 +22,27 @@ enum class Severity }; // Make sure that the slang.h severity constants match those defined here -static_assert(SLANG_SEVERITY_DISABLED == int(Severity::Disable), "mismatched Severity enum values"); -static_assert(SLANG_SEVERITY_NOTE == int(Severity::Note), "mismatched Severity enum values"); -static_assert(SLANG_SEVERITY_WARNING == int(Severity::Warning), "mismatched Severity enum values"); -static_assert(SLANG_SEVERITY_ERROR == int(Severity::Error), "mismatched Severity enum values"); -static_assert(SLANG_SEVERITY_FATAL == int(Severity::Fatal), "mismatched Severity enum values"); -static_assert(SLANG_SEVERITY_INTERNAL == int(Severity::Internal), "mismatched Severity enum values"); +static_assert(SLANG_SEVERITY_DISABLED == int(Severity::Disable), "mismatched Severity enum values"); +static_assert(SLANG_SEVERITY_NOTE == int(Severity::Note), "mismatched Severity enum values"); +static_assert(SLANG_SEVERITY_WARNING == int(Severity::Warning), "mismatched Severity enum values"); +static_assert(SLANG_SEVERITY_ERROR == int(Severity::Error), "mismatched Severity enum values"); +static_assert(SLANG_SEVERITY_FATAL == int(Severity::Fatal), "mismatched Severity enum values"); +static_assert( + SLANG_SEVERITY_INTERNAL == int(Severity::Internal), + "mismatched Severity enum values"); // TODO(tfoley): move this into a source file... inline const char* getSeverityName(Severity severity) { switch (severity) { - case Severity::Disable: return "ignored"; - case Severity::Note: return "note"; - case Severity::Warning: return "warning"; - case Severity::Error: return "error"; - case Severity::Fatal: return "fatal error"; - case Severity::Internal: return "internal error"; - default: return "unknown error"; + case Severity::Disable: return "ignored"; + case Severity::Note: return "note"; + case Severity::Warning: return "warning"; + case Severity::Error: return "error"; + case Severity::Fatal: return "fatal error"; + case Severity::Internal: return "internal error"; + default: return "unknown error"; } } @@ -52,7 +52,7 @@ struct DiagnosticInfo { int id; Severity severity; - char const* name; ///< Unique name + char const* name; ///< Unique name char const* messageFormat; }; @@ -64,15 +64,8 @@ public: int ErrorID; Severity severity; - Diagnostic() - { - ErrorID = -1; - } - Diagnostic( - const String & msg, - int id, - const SourceLoc & pos, - Severity severity) + Diagnostic() { ErrorID = -1; } + Diagnostic(const String& msg, int id, const SourceLoc& pos, Severity severity) : severity(severity) { Message = msg; @@ -105,14 +98,17 @@ void printDiagnosticArg(StringBuilder& sb, IRInst* irObject); class Modifier; void printDiagnosticArg(StringBuilder& sb, Modifier* modifier); - + template void printDiagnosticArg(StringBuilder& sb, RefPtr ptr) { printDiagnosticArg(sb, ptr.Ptr()); } -inline SourceLoc getDiagnosticPos(SourceLoc const& pos) { return pos; } +inline SourceLoc getDiagnosticPos(SourceLoc const& pos) +{ + return pos; +} SourceLoc getDiagnosticPos(Token const& token); @@ -136,39 +132,43 @@ struct DiagnosticArg template DiagnosticArg(T const& arg) - : data((void*)&arg) - , printFunc(&Helper::printFunc) - {} + : data((void*)&arg), printFunc(&Helper::printFunc) + { + } }; class DiagnosticSink { public: - /// Flags to control some aspects of Diagnostic sink behavior + /// Flags to control some aspects of Diagnostic sink behavior typedef uint32_t Flags; - struct Flag + struct Flag { - enum Enum: Flags + enum Enum : Flags { - VerbosePath = 0x1, ///< Will display a more verbose path (if available) - such as a canonical or absolute path - SourceLocationLine = 0x2, ///< If set will display the location line if source is available - HumaneLoc = 0x4, ///< If set will display humane locs (filename/line number) information - TreatWarningsAsErrors = 0x8, ///< If set will turn all Warning type messages (after overrides) into Error type messages - LanguageServer = 0x10, ///< If set will format message in a way that is suitable for language server + VerbosePath = 0x1, ///< Will display a more verbose path (if available) - such as a + ///< canonical or absolute path + SourceLocationLine = + 0x2, ///< If set will display the location line if source is available + HumaneLoc = 0x4, ///< If set will display humane locs (filename/line number) information + TreatWarningsAsErrors = 0x8, ///< If set will turn all Warning type messages (after + ///< overrides) into Error type messages + LanguageServer = + 0x10, ///< If set will format message in a way that is suitable for language server }; }; - /// Used by diagnostic sink to be able to underline tokens. If not defined on the DiagnosticSink, - /// will only display a caret at the SourceLoc - typedef UnownedStringSlice(*SourceLocationLexer)(const UnownedStringSlice& text); + /// Used by diagnostic sink to be able to underline tokens. If not defined on the + /// DiagnosticSink, will only display a caret at the SourceLoc + typedef UnownedStringSlice (*SourceLocationLexer)(const UnownedStringSlice& text); - /// Get the total amount of errors that have taken place on this DiagnosticSink + /// Get the total amount of errors that have taken place on this DiagnosticSink SLANG_FORCE_INLINE int getErrorCount() { return m_errorCount; } template - bool diagnose(P const& pos, DiagnosticInfo const& info, Args const&... args ) + bool diagnose(P const& pos, DiagnosticInfo const& info, Args const&... args) { - DiagnosticArg as[] = { DiagnosticArg(args)... }; + DiagnosticArg as[] = {DiagnosticArg(args)...}; return diagnoseImpl(getDiagnosticPos(pos), info, sizeof...(args), as); } @@ -179,10 +179,10 @@ public: return diagnoseImpl(getDiagnosticPos(pos), info, 0, nullptr); } - // Useful for notes on existing diagnostics, where it would be redundant to display the same line again. - // (Ideally we would print the error/warning and notes in one call...) + // Useful for notes on existing diagnostics, where it would be redundant to display the same + // line again. (Ideally we would print the error/warning and notes in one call...) template - bool diagnoseWithoutSourceView(P const& pos, DiagnosticInfo const& info, Args const&... args ) + bool diagnoseWithoutSourceView(P const& pos, DiagnosticInfo const& info, Args const&... args) { const auto fs = this->getFlags(); this->resetFlag(Flag::SourceLocationLine); @@ -193,83 +193,92 @@ public: return result; } - // Add a diagnostic with raw text - // (used when we get errors from a downstream compiler) + // Add a diagnostic with raw text + // (used when we get errors from a downstream compiler) void diagnoseRaw(Severity severity, char const* message); void diagnoseRaw(Severity severity, const UnownedStringSlice& message); - /// During propagation of an exception for an internal - /// error, note that this source location was involved + /// During propagation of an exception for an internal + /// error, note that this source location was involved void noteInternalErrorLoc(SourceLoc const& loc); - /// Create a blob containing diagnostics if there were any errors. - /// *note* only works if writer is not set, the blob is created from outputBuffer + /// Create a blob containing diagnostics if there were any errors. + /// *note* only works if writer is not set, the blob is created from outputBuffer SlangResult getBlobIfNeeded(ISlangBlob** outBlob); - /// Get the source manager used + /// Get the source manager used SourceManager* getSourceManager() const { return m_sourceManager; } - /// Set the source manager used for lookup of source locs + /// Set the source manager used for lookup of source locs void setSourceManager(SourceManager* inSourceManager) { m_sourceManager = inSourceManager; } - /// Set the flags - void setFlags(Flags flags) { m_flags = flags; } - /// Get the flags + /// Set the flags + void setFlags(Flags flags) { m_flags = flags; } + /// Get the flags Flags getFlags() const { return m_flags; } - /// Set a flag + /// Set a flag void setFlag(Flag::Enum flag) { m_flags |= Flags(flag); } - /// Reset a flag + /// Reset a flag void resetFlag(Flag::Enum flag) { m_flags &= ~Flags(flag); } - /// Test if flag is set + /// Test if flag is set bool isFlagSet(Flag::Enum flag) { return (m_flags & Flags(flag)) != 0; } - /// Sets an override on the severity of a specific diagnostic message (by numeric identifier) - /// info can be set to nullptr if only to override - void overrideDiagnosticSeverity(int diagnosticId, Severity overrideSeverity, const DiagnosticInfo* info = nullptr); + /// Sets an override on the severity of a specific diagnostic message (by numeric identifier) + /// info can be set to nullptr if only to override + void overrideDiagnosticSeverity( + int diagnosticId, + Severity overrideSeverity, + const DiagnosticInfo* info = nullptr); - /// Get the (optional) diagnostic sink lexer. This is used to - /// improve quality of highlighting a locations token. If not set, will just have a single - /// character caret at location + /// Get the (optional) diagnostic sink lexer. This is used to + /// improve quality of highlighting a locations token. If not set, will just have a single + /// character caret at location SourceLocationLexer getSourceLocationLexer() const { return m_sourceLocationLexer; } - /// Set the maximum length (in chars) of a source line displayed. Set to 0 for no limit + /// Set the maximum length (in chars) of a source line displayed. Set to 0 for no limit void setSourceLineMaxLength(Index length) { m_sourceLineMaxLength = length; } Index getSourceLineMaxLength() const { return m_sourceLineMaxLength; } - /// The parent sink is another sink that will receive diagnostics from this sink. + /// The parent sink is another sink that will receive diagnostics from this sink. void setParentSink(DiagnosticSink* parentSink) { m_parentSink = parentSink; } DiagnosticSink* getParentSink() const { return m_parentSink; } - /// Reset state. - /// Resets error counts. Resets the output buffer. + /// Reset state. + /// Resets error counts. Resets the output buffer. void reset(); - /// Initialize state. + /// Initialize state. void init(SourceManager* sourceManager, SourceLocationLexer sourceLocationLexer); - /// Ctor - DiagnosticSink(SourceManager* sourceManager, SourceLocationLexer sourceLocationLexer) { init(sourceManager, sourceLocationLexer); } - /// Default Ctor - DiagnosticSink(): - m_sourceManager(nullptr), - m_sourceLocationLexer(nullptr) + /// Ctor + DiagnosticSink(SourceManager* sourceManager, SourceLocationLexer sourceLocationLexer) + { + init(sourceManager, sourceLocationLexer); + } + /// Default Ctor + DiagnosticSink() + : m_sourceManager(nullptr), m_sourceLocationLexer(nullptr) { } // Public members - /// The outputBuffer will contain any diagnostics *iff* the writer is *not* set + /// The outputBuffer will contain any diagnostics *iff* the writer is *not* set StringBuilder outputBuffer; - /// If a writer is set output will *not* be written to the outputBuffer + /// If a writer is set output will *not* be written to the outputBuffer ISlangWriter* writer = nullptr; protected: // Returns true if a diagnostic is actually written. - bool diagnoseImpl(SourceLoc const& pos, DiagnosticInfo info, int argCount, DiagnosticArg const* args); + bool diagnoseImpl( + SourceLoc const& pos, + DiagnosticInfo info, + int argCount, + DiagnosticArg const* args); bool diagnoseImpl(DiagnosticInfo const& info, const UnownedStringSlice& formattedMessage); Severity getEffectiveMessageSeverity(DiagnosticInfo const& info); - /// If set all diagnostics (as formatted by *this* sink, will be routed to the parent). + /// If set all diagnostics (as formatted by *this* sink, will be routed to the parent). DiagnosticSink* m_parentSink = nullptr; int m_errorCount = 0; @@ -277,7 +286,7 @@ protected: /// If 0, then there is no limit, otherwise max amount of chars of the source line location /// We don't know the size of a terminal in general, but for now we'll guess 120. - Index m_sourceLineMaxLength = 120; + Index m_sourceLineMaxLength = 120; Flags m_flags = 0; @@ -285,26 +294,27 @@ protected: SourceManager* m_sourceManager = nullptr; SourceLocationLexer m_sourceLocationLexer; - + // Configuration that allows the user to control the severity of certain diagnostic messages Dictionary m_severityOverrides; }; - /// An `ISlangWriter` that writes directly to a diagnostic sink. +/// An `ISlangWriter` that writes directly to a diagnostic sink. class DiagnosticSinkWriter : public AppendBufferWriter { public: typedef AppendBufferWriter Super; DiagnosticSinkWriter(DiagnosticSink* sink) - : Super(WriterFlag::IsStatic) - , m_sink(sink) - {} + : Super(WriterFlag::IsStatic), m_sink(sink) + { + } // ISlangWriter - SLANG_NO_THROW virtual SlangResult SLANG_MCALL write(const char* chars, size_t numChars) SLANG_OVERRIDE + SLANG_NO_THROW virtual SlangResult SLANG_MCALL write(const char* chars, size_t numChars) + SLANG_OVERRIDE { - m_sink->diagnoseRaw(Severity::Note, UnownedStringSlice(chars, chars+numChars)); + m_sink->diagnoseRaw(Severity::Note, UnownedStringSlice(chars, chars + numChars)); return SLANG_OK; } @@ -317,36 +327,36 @@ class DiagnosticsLookup : public RefObject public: static const Index kArenaInitialSize = 65536; - /// Will take into account the slice name could be using different conventions + /// Will take into account the slice name could be using different conventions const DiagnosticInfo* findDiagnosticByName(const UnownedStringSlice& slice) const; - /// The name must be as defined in the diagnostics exactly, typically lower camel + /// The name must be as defined in the diagnostics exactly, typically lower camel const DiagnosticInfo* findDiagnosticByExactName(const UnownedStringSlice& slice) const; - /// Get a diagnostic by it's id. - /// NOTE! That it is possible for multiple diagnostics to have the same id. This will return - /// the first added + /// Get a diagnostic by it's id. + /// NOTE! That it is possible for multiple diagnostics to have the same id. This will return + /// the first added const DiagnosticInfo* getDiagnosticById(Int id) const; - /// info must stay in scope + /// info must stay in scope Index add(const DiagnosticInfo* info); - /// Infos referenced must remain in scope - void add(const DiagnosticInfo*const* infos, Index infosCount); + /// Infos referenced must remain in scope + void add(const DiagnosticInfo* const* infos, Index infosCount); - /// NOTE! Name must stay in scope as long as the diagnostics lookup. - /// If not possible add it to the arena to keep in scope. + /// NOTE! Name must stay in scope as long as the diagnostics lookup. + /// If not possible add it to the arena to keep in scope. void addAlias(const char* name, const char* diagnosticName); - /// Get the diagnostics held in this lookup + /// Get the diagnostics held in this lookup const List& getDiagnostics() const { return m_diagnostics; } - /// Get the associated arena + /// Get the associated arena MemoryArena& getArena() { return m_arena; } - /// NOTE! diagnostics must stay in scope for lifetime of lookup - DiagnosticsLookup(const DiagnosticInfo*const* diagnostics, Index diagnosticsCount); + /// NOTE! diagnostics must stay in scope for lifetime of lookup + DiagnosticsLookup(const DiagnosticInfo* const* diagnostics, Index diagnosticsCount); DiagnosticsLookup(); -protected: +protected: void _addName(const char* name, Index diagnosticIndex); Index _findDiagnosticIndexByExactName(const UnownedStringSlice& slice) const; @@ -360,6 +370,6 @@ protected: MemoryArena m_arena; }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-doc-extractor.cpp b/source/compiler-core/slang-doc-extractor.cpp index 9a625f3e0..d8a27822f 100644 --- a/source/compiler-core/slang-doc-extractor.cpp +++ b/source/compiler-core/slang-doc-extractor.cpp @@ -3,23 +3,28 @@ #include "../core/slang-string-util.h" -namespace Slang { +namespace Slang +{ /* TODO(JS): -* If Decls hand SourceRange, then we could use the range to simplify getting the Post markup, as will be trivial to get to the 'end' +* If Decls hand SourceRange, then we could use the range to simplify getting the Post markup, as +will be trivial to get to the 'end' * Need to handle preceeding * in some markup styles -* If we want to be able to disable markup we need a mechanism to do this. Probably define source ranges. +* If we want to be able to disable markup we need a mechanism to do this. Probably define source +ranges. * Need a way to take the extracted markup and produce suitable markdown ** This will need to display the decoration appropriately */ -/* static */UnownedStringSlice DocMarkupExtractor::removeStart(MarkupType type, const UnownedStringSlice& comment) +/* static */ UnownedStringSlice DocMarkupExtractor::removeStart( + MarkupType type, + const UnownedStringSlice& comment) { switch (type) { - case MarkupType::BlockBefore: + case MarkupType::BlockBefore: { if (comment.startsWith(UnownedStringSlice::fromLiteral("/**")) || comment.startsWith(UnownedStringSlice::fromLiteral("/*!"))) @@ -28,10 +33,10 @@ namespace Slang { return comment.tail(3); } return comment; - } - case MarkupType::BlockAfter: + } + case MarkupType::BlockAfter: { - + if (comment.startsWith(UnownedStringSlice::fromLiteral("/**<")) || comment.startsWith(UnownedStringSlice::fromLiteral("/*!<"))) { @@ -40,7 +45,7 @@ namespace Slang { } return comment; } - case MarkupType::OrdinaryBlockBefore: + case MarkupType::OrdinaryBlockBefore: { if (comment.startsWith(UnownedStringSlice::fromLiteral("/*"))) { @@ -49,29 +54,34 @@ namespace Slang { } return comment; } - case MarkupType::LineBangBefore: + case MarkupType::LineBangBefore: { - return comment.startsWith(UnownedStringSlice::fromLiteral("//!")) ? comment.tail(3) : comment; + return comment.startsWith(UnownedStringSlice::fromLiteral("//!")) ? comment.tail(3) + : comment; } - case MarkupType::LineSlashBefore: + case MarkupType::LineSlashBefore: { - return comment.startsWith(UnownedStringSlice::fromLiteral("///")) ? comment.tail(3) : comment; + return comment.startsWith(UnownedStringSlice::fromLiteral("///")) ? comment.tail(3) + : comment; } - case MarkupType::OrdinaryLineBefore: - case MarkupType::OrdinaryLineAfter: + case MarkupType::OrdinaryLineBefore: + case MarkupType::OrdinaryLineAfter: { - return comment.startsWith(UnownedStringSlice::fromLiteral("//")) ? comment.tail(2) : comment; + return comment.startsWith(UnownedStringSlice::fromLiteral("//")) ? comment.tail(2) + : comment; } - case MarkupType::LineBangAfter: + case MarkupType::LineBangAfter: { /// //!< Can be multiple lines - return comment.startsWith(UnownedStringSlice::fromLiteral("//!<")) ? comment.tail(4) : comment; + return comment.startsWith(UnownedStringSlice::fromLiteral("//!<")) ? comment.tail(4) + : comment; } - case MarkupType::LineSlashAfter: + case MarkupType::LineSlashAfter: { - return comment.startsWith(UnownedStringSlice::fromLiteral("///<")) ? comment.tail(4) : comment; + return comment.startsWith(UnownedStringSlice::fromLiteral("///<")) ? comment.tail(4) + : comment; } - default: break; + default: break; } return comment; } @@ -106,37 +116,37 @@ static Index _findTokenIndex(SourceLoc loc, const Token* toks, Index numToks) return -1; } -/* static */DocMarkupExtractor::MarkupFlags DocMarkupExtractor::getFlags(MarkupType type) +/* static */ DocMarkupExtractor::MarkupFlags DocMarkupExtractor::getFlags(MarkupType type) { switch (type) { - default: - case MarkupType::None: return 0; - case MarkupType::BlockBefore: return MarkupFlag::Before | MarkupFlag::IsBlock; - case MarkupType::BlockAfter: return MarkupFlag::After | MarkupFlag::IsBlock; - case MarkupType::OrdinaryBlockBefore: return MarkupFlag::Before | MarkupFlag::IsBlock; - - case MarkupType::LineBangBefore: return MarkupFlag::Before | MarkupFlag::IsMultiToken; - case MarkupType::LineSlashBefore: return MarkupFlag::Before | MarkupFlag::IsMultiToken; - case MarkupType::OrdinaryLineBefore: return MarkupFlag::Before | MarkupFlag::IsMultiToken; - - case MarkupType::LineBangAfter: return MarkupFlag::After | MarkupFlag::IsMultiToken; - case MarkupType::LineSlashAfter: return MarkupFlag::After | MarkupFlag::IsMultiToken; - case MarkupType::OrdinaryLineAfter: return MarkupFlag::After | MarkupFlag::IsMultiToken; - + default: + case MarkupType::None: return 0; + case MarkupType::BlockBefore: return MarkupFlag::Before | MarkupFlag::IsBlock; + case MarkupType::BlockAfter: return MarkupFlag::After | MarkupFlag::IsBlock; + case MarkupType::OrdinaryBlockBefore: return MarkupFlag::Before | MarkupFlag::IsBlock; + + case MarkupType::LineBangBefore: return MarkupFlag::Before | MarkupFlag::IsMultiToken; + case MarkupType::LineSlashBefore: return MarkupFlag::Before | MarkupFlag::IsMultiToken; + case MarkupType::OrdinaryLineBefore: return MarkupFlag::Before | MarkupFlag::IsMultiToken; + + case MarkupType::LineBangAfter: return MarkupFlag::After | MarkupFlag::IsMultiToken; + case MarkupType::LineSlashAfter: return MarkupFlag::After | MarkupFlag::IsMultiToken; + case MarkupType::OrdinaryLineAfter: return MarkupFlag::After | MarkupFlag::IsMultiToken; } } -/* static */DocMarkupExtractor::MarkupType DocMarkupExtractor::findMarkupType(const Token& tok) +/* static */ DocMarkupExtractor::MarkupType DocMarkupExtractor::findMarkupType(const Token& tok) { switch (tok.type) { - case TokenType::BlockComment: + case TokenType::BlockComment: { UnownedStringSlice slice = tok.getContent(); if (slice.getLength() >= 3 && (slice[2] == '!' || slice[2] == '*')) { - return (slice.getLength() >= 4 && slice[3] == '<') ? MarkupType::BlockAfter : MarkupType::BlockBefore; + return (slice.getLength() >= 4 && slice[3] == '<') ? MarkupType::BlockAfter + : MarkupType::BlockBefore; } else { @@ -144,25 +154,28 @@ static Index _findTokenIndex(SourceLoc loc, const Token* toks, Index numToks) } break; } - case TokenType::LineComment: + case TokenType::LineComment: { UnownedStringSlice slice = tok.getContent(); if (slice.getLength() >= 3) { if (slice[2] == '!') { - return (slice.getLength() >= 4 && slice[3] == '<') ? MarkupType::LineBangAfter : MarkupType::LineBangBefore; + return (slice.getLength() >= 4 && slice[3] == '<') ? MarkupType::LineBangAfter + : MarkupType::LineBangBefore; } else if (slice[2] == '/') { - return (slice.getLength() >= 4 && slice[3] == '<') ? MarkupType::LineSlashAfter : MarkupType::LineSlashBefore; + return (slice.getLength() >= 4 && slice[3] == '<') + ? MarkupType::LineSlashAfter + : MarkupType::LineSlashBefore; } } return (tok.flags & TokenFlag::AtStartOfLine) != 0 ? MarkupType::OrdinaryLineBefore : MarkupType::OrdinaryLineAfter; break; } - default: break; + default: break; } return MarkupType::None; } @@ -172,7 +185,8 @@ static Index _calcWhitespaceIndent(const UnownedStringSlice& line) // TODO(JS): For now we ignore tabs and just work out indentation based on spaces/assume ASCII Index indent = 0; const Index count = line.getLength(); - for (; indent < count && line[indent] == ' '; indent++); + for (; indent < count && line[indent] == ' '; indent++) + ; return indent; } @@ -182,7 +196,10 @@ static Index _calcIndent(const UnownedStringSlice& line) return line.getLength(); } -static void _appendUnindenttedLine(const UnownedStringSlice& line, Index maxIndent, StringBuilder& out) +static void _appendUnindenttedLine( + const UnownedStringSlice& line, + Index maxIndent, + StringBuilder& out) { Index indent = _calcWhitespaceIndent(line); @@ -196,19 +213,22 @@ static void _appendUnindenttedLine(const UnownedStringSlice& line, Index maxInde out.append(line.tail(indent)); } -SlangResult DocMarkupExtractor::_extractMarkup(const FindInfo& info, const FoundMarkup& foundMarkup, StringBuilder& out) +SlangResult DocMarkupExtractor::_extractMarkup( + const FindInfo& info, + const FoundMarkup& foundMarkup, + StringBuilder& out) { SourceView* sourceView = info.sourceView; SourceFile* sourceFile = sourceView->getSourceFile(); // Here we want to produce the text that is implied by the markup tokens. // We want to removing surrounding markup, and to also keep appropriate indentation - + switch (foundMarkup.type) { - case MarkupType::BlockBefore: - case MarkupType::BlockAfter: - case MarkupType::OrdinaryBlockBefore: + case MarkupType::BlockBefore: + case MarkupType::BlockAfter: + case MarkupType::OrdinaryBlockBefore: { // We should only have a single line SLANG_ASSERT(foundMarkup.range.getCount() == 1); @@ -239,9 +259,10 @@ SlangResult DocMarkupExtractor::_extractMarkup(const FindInfo& info, const Found { if (startLine.isMemoryContained(line.begin())) { - // For now we'll ignore tabs, and that the indent amount is, the amount of *byte* - // NOTE! This is only appropriate for ASCII without tabs. - maxIndent = _calcIndent(UnownedStringSlice(startLine.begin(), line.begin())); + // For now we'll ignore tabs, and that the indent amount is, the amount of + // *byte* NOTE! This is only appropriate for ASCII without tabs. + maxIndent = + _calcIndent(UnownedStringSlice(startLine.begin(), line.begin())); // Let's strip the start stuff line = removeStart(foundMarkup.type, line); @@ -250,7 +271,8 @@ SlangResult DocMarkupExtractor::_extractMarkup(const FindInfo& info, const Found if (i == linesCount - 1) { - SLANG_ASSERT(line.tail(line.getLength() - 2) == UnownedStringSlice::fromLiteral("*/")); + SLANG_ASSERT( + line.tail(line.getLength() - 2) == UnownedStringSlice::fromLiteral("*/")); // Remove the */ at the end of the line line = line.head(line.getLength() - 2); } @@ -263,9 +285,10 @@ SlangResult DocMarkupExtractor::_extractMarkup(const FindInfo& info, const Found { unindentedLine.append(line); } - + // If the first or last line are all white space, just ignore them - if ((i == linesCount - 1 || i == 0) && unindentedLine.getUnownedSlice().trim().getLength() == 0) + if ((i == linesCount - 1 || i == 0) && + unindentedLine.getUnownedSlice().trim().getLength() == 0) { continue; } @@ -276,18 +299,19 @@ SlangResult DocMarkupExtractor::_extractMarkup(const FindInfo& info, const Found break; } - case MarkupType::OrdinaryLineBefore: - case MarkupType::OrdinaryLineAfter: - case MarkupType::LineBangBefore: - case MarkupType::LineSlashBefore: - case MarkupType::LineBangAfter: - case MarkupType::LineSlashAfter: + case MarkupType::OrdinaryLineBefore: + case MarkupType::OrdinaryLineAfter: + case MarkupType::LineBangBefore: + case MarkupType::LineSlashBefore: + case MarkupType::LineBangAfter: + case MarkupType::LineSlashAfter: { - // Holds the lines extracted, they may have some white space indenting (like the space at the start of //) + // Holds the lines extracted, they may have some white space indenting (like the space + // at the start of //) List lines; const auto& range = foundMarkup.range; - for (Index i = range.start; i < range.end; ++ i) + for (Index i = range.start; i < range.end; ++i) { const auto& tok = info.tokenList->m_tokens[i]; UnownedStringSlice line = tok.getContent(); @@ -322,7 +346,7 @@ SlangResult DocMarkupExtractor::_extractMarkup(const FindInfo& info, const Found break; } - default: return SLANG_FAIL; + default: return SLANG_FAIL; } return SLANG_OK; @@ -344,22 +368,24 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio switch (tok.type) { - case TokenType::LBrace: - case TokenType::LBracket: - case TokenType::LParent: - case TokenType::OpLess: + case TokenType::LBrace: + case TokenType::LBracket: + case TokenType::LParent: + case TokenType::OpLess: { openCount += direction; - if (openCount < 0) return -1; + if (openCount < 0) + return -1; break; } - case TokenType::RBracket: + case TokenType::RBracket: { openCount -= direction; - if (openCount < 0) return -1; + if (openCount < 0) + return -1; break; } - case TokenType::OpGreater: + case TokenType::OpGreater: { if (location == Location::AfterGenericParam && openCount == 0) { @@ -367,11 +393,12 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio } openCount -= direction; - if (openCount < 0) return -1; + if (openCount < 0) + return -1; break; } - case TokenType::RParent: + case TokenType::RParent: { if (openCount == 0 && location == Location::AfterParam) { @@ -379,10 +406,11 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio } openCount -= direction; - if (openCount < 0) return -1; + if (openCount < 0) + return -1; break; } - case TokenType::RBrace: + case TokenType::RBrace: { // If we haven't hit a candidate yet before hitting } it's not going to work if (location == Location::Before || location == Location::AfterEnumCase) @@ -391,8 +419,8 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio } break; } - case TokenType::BlockComment: - case TokenType::LineComment: + case TokenType::BlockComment: + case TokenType::LineComment: { if (openCount == 0) { @@ -407,7 +435,8 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio { return i; } - // If we are looking for enum cases, and the markup is after, we'll assume this is it + // If we are looking for enum cases, and the markup is after, we'll assume this + // is it if (isAfter(location) && isAfter(markupType)) { return i; @@ -415,11 +444,12 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio } break; } - case TokenType::Comma: + case TokenType::Comma: { if (openCount == 0) - { - if (location == Location::AfterParam || location == Location::AfterEnumCase || location == Location::AfterGenericParam) + { + if (location == Location::AfterParam || location == Location::AfterEnumCase || + location == Location::AfterGenericParam) { return i + 1; } @@ -432,7 +462,7 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio break; } - case TokenType::Semicolon: + case TokenType::Semicolon: { // If we haven't hit a candidate yet it's not going to work if (location == Location::Before) @@ -445,14 +475,18 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio } break; } - default: break; + default: break; } } return -1; } -/* static */bool DocMarkupExtractor::_isTokenOnLineIndex(SourceView* sourceView, MarkupType type, const Token& tok, Index lineIndex) +/* static */ bool DocMarkupExtractor::_isTokenOnLineIndex( + SourceView* sourceView, + MarkupType type, + const Token& tok, + Index lineIndex) { SourceFile* sourceFile = sourceView->getSourceFile(); const int offset = sourceView->getRange().getOffset(tok.loc); @@ -462,7 +496,8 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio if (flags & MarkupFlag::IsBlock) { // Either the start or the end of the block have to be on the specified line - return sourceFile->isOffsetOnLine(offset, lineIndex) || sourceFile->isOffsetOnLine(offset + tok.charsCount, lineIndex); + return sourceFile->isOffsetOnLine(offset, lineIndex) || + sourceFile->isOffsetOnLine(offset + tok.charsCount, lineIndex); } else { @@ -471,12 +506,15 @@ Index DocMarkupExtractor::_findStartIndex(const FindInfo& info, Location locatio } } -SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, Location location, FoundMarkup& out) +SlangResult DocMarkupExtractor::_findMarkup( + const FindInfo& info, + Location location, + FoundMarkup& out) { out.reset(); const auto& toks = info.tokenList->m_tokens; - + // The starting token index Index startIndex = _findStartIndex(info, location); if (startIndex <= 0) @@ -490,7 +528,7 @@ SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, Location locat // Let's lookup the line index where this occurred const int startOffset = sourceView->getRange().getOffset(toks[startIndex].loc); - // The line index that the markoff starts from + // The line index that the markoff starts from Index lineIndex = sourceFile->calcLineIndexFromOffset(startOffset); if (lineIndex < 0) { @@ -498,12 +536,13 @@ SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, Location locat } const Index searchDirection = isBefore(location) ? -1 : 1; - + // Get the type and flags const MarkupType type = findMarkupType(toks[startIndex]); const MarkupFlags flags = getFlags(type); - const MarkupFlag::Enum requiredFlag = isBefore(location) ? MarkupFlag::Before : MarkupFlag::After; + const MarkupFlag::Enum requiredFlag = + isBefore(location) ? MarkupFlag::Before : MarkupFlag::After; if ((flags & requiredFlag) == 0) { return SLANG_E_NOT_FOUND; @@ -567,14 +606,19 @@ SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, Location locat // Okay we've found the markup out.type = type; out.location = location; - out.range = IndexRange{ startIndex, endIndex }; + out.range = IndexRange{startIndex, endIndex}; SLANG_ASSERT(out.range.getCount() > 0); return SLANG_OK; } -SlangResult DocMarkupExtractor::_findFirstMarkup(const FindInfo& info, const Location* locs, Index locCount, FoundMarkup& out, Index& outIndex) +SlangResult DocMarkupExtractor::_findFirstMarkup( + const FindInfo& info, + const Location* locs, + Index locCount, + FoundMarkup& out, + Index& outIndex) { Index i = 0; for (; i < locCount; ++i) @@ -589,7 +633,11 @@ SlangResult DocMarkupExtractor::_findFirstMarkup(const FindInfo& info, const Loc return SLANG_E_NOT_FOUND; } -SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, const Location* locs, Index locCount, FoundMarkup& out) +SlangResult DocMarkupExtractor::_findMarkup( + const FindInfo& info, + const Location* locs, + Index locCount, + FoundMarkup& out) { Index foundIndex; SLANG_RETURN_ON_FAIL(_findFirstMarkup(info, locs, locCount, out, foundIndex)); @@ -611,53 +659,59 @@ SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, const Location } -SlangResult DocMarkupExtractor::_findMarkup(const FindInfo& info, SearchStyle searchStyle, FoundMarkup& out) +SlangResult DocMarkupExtractor::_findMarkup( + const FindInfo& info, + SearchStyle searchStyle, + FoundMarkup& out) { switch (searchStyle) { - default: - case SearchStyle::None: + default: + case SearchStyle::None: { return SLANG_E_NOT_FOUND; } - case SearchStyle::EnumCase: + case SearchStyle::EnumCase: { - Location locs[] = { Location::Before, Location::AfterEnumCase }; + Location locs[] = {Location::Before, Location::AfterEnumCase}; return _findMarkup(info, locs, SLANG_COUNT_OF(locs), out); } - case SearchStyle::Param: + case SearchStyle::Param: { - Location locs[] = { Location::Before, Location::AfterParam }; + Location locs[] = {Location::Before, Location::AfterParam}; return _findMarkup(info, locs, SLANG_COUNT_OF(locs), out); } - case SearchStyle::Before: + case SearchStyle::Before: { return _findMarkup(info, Location::Before, out); } - case SearchStyle::Function: + case SearchStyle::Function: { return _findMarkup(info, Location::Before, out); } - case SearchStyle::Attribute: + case SearchStyle::Attribute: { FindInfo newInfo = info; newInfo.tokenIndex -= 2; return _findMarkup(newInfo, Location::Before, out); } - case SearchStyle::Variable: + case SearchStyle::Variable: { - Location locs[] = { Location::Before, Location::AfterSemicolon }; + Location locs[] = {Location::Before, Location::AfterSemicolon}; return _findMarkup(info, locs, SLANG_COUNT_OF(locs), out); } - case SearchStyle::GenericParam: + case SearchStyle::GenericParam: { - Location locs[] = { Location::Before, Location::AfterGenericParam }; + Location locs[] = {Location::Before, Location::AfterGenericParam}; return _findMarkup(info, locs, SLANG_COUNT_OF(locs), out); } } } -static void _calcLineVisibility(SourceView* sourceView, const TokenList& toks, List& outLineVisibility) +static void _calcLineVisibility( + SourceView* sourceView, + const TokenList& toks, + List& outLineVisibility) { SourceFile* sourceFile = sourceView->getSourceFile(); const auto& lineOffsets = sourceFile->getLineBreakOffsets(); @@ -713,21 +767,27 @@ static void _calcLineVisibility(SourceView* sourceView, const TokenList& toks, L } // Fill in the remaining - for (Index i = lastLine; i < outLineVisibility.getCount(); ++ i) + for (Index i = lastLine; i < outLineVisibility.getCount(); ++i) { outLineVisibility[i] = lastVisibility; } } -SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inputCount, SourceManager* sourceManager, DiagnosticSink* sink, List& outViews, List& out) +SlangResult DocMarkupExtractor::extract( + const SearchItemInput* inputs, + Index inputCount, + SourceManager* sourceManager, + DiagnosticSink* sink, + List& outViews, + List& out) { struct Entry { - Index viewIndex; ///< The view/file index this loc is found in - SourceLoc::RawValue locOrOffset; ///< Can be a loc or an offset into the file + Index viewIndex; ///< The view/file index this loc is found in + SourceLoc::RawValue locOrOffset; ///< Can be a loc or an offset into the file - SearchStyle searchStyle; ///< The search style when looking for an item - Index inputIndex; ///< The index to this item in the input + SearchStyle searchStyle; ///< The search style when looking for an item + Index inputIndex; ///< The index to this item in the input }; List entries; @@ -739,14 +799,15 @@ SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inp const auto& input = inputs[i]; Entry& entry = entries[i]; entry.inputIndex = i; - entry.viewIndex = -1; //< We don't know what file/view it's in + entry.viewIndex = -1; //< We don't know what file/view it's in entry.locOrOffset = input.sourceLoc.getRaw(); entry.searchStyle = input.searchStyle; } } // Sort them into loc order - entries.sort([](const Entry& a, const Entry& b) -> bool { return a.locOrOffset < b.locOrOffset; }); + entries.sort( + [](const Entry& a, const Entry& b) -> bool { return a.locOrOffset < b.locOrOffset; }); { SourceView* sourceView = nullptr; @@ -774,8 +835,10 @@ SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inp // We want only one view per SourceFile SourceFile* sourceFile = sourceView->getSourceFile(); - // NOTE! The view found might be different than sourceView. - viewIndex = outViews.findFirstIndex([&](SourceView* currentView) -> bool { return currentView->getSourceFile() == sourceFile; }); + // NOTE! The view found might be different than sourceView. + viewIndex = outViews.findFirstIndex( + [&](SourceView* currentView) -> bool + { return currentView->getSourceFile() == sourceFile; }); if (viewIndex < 0) { @@ -789,12 +852,17 @@ SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inp // Set the file index entry.viewIndex = viewIndex; - // Set as the offset within the file + // Set as the offset within the file entry.locOrOffset = sourceView->getRange().getOffset(loc); } // Sort into view/file and then offset order - entries.sort([](const Entry& a, const Entry& b) -> bool { return (a.viewIndex < b.viewIndex) || ((a.viewIndex == b.viewIndex) && a.locOrOffset < b.locOrOffset); }); + entries.sort( + [](const Entry& a, const Entry& b) -> bool + { + return (a.viewIndex < b.viewIndex) || + ((a.viewIndex == b.viewIndex) && a.locOrOffset < b.locOrOffset); + }); } { @@ -854,7 +922,8 @@ SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inp // Get the offset within the source file const uint32_t offset = entry.locOrOffset; - // We need to get the loc in the source views space, so we look up appropriately in the list of tokens (which uses the views loc range) + // We need to get the loc in the source views space, so we look up appropriately in the + // list of tokens (which uses the views loc range) const SourceLoc loc = sourceView->getRange().getSourceLocFromOffset(offset); // Work out the line number @@ -864,7 +933,8 @@ SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inp dst.visibilty = lineVisibility[lineIndex]; // Okay, lets find the token index with a binary chop - Index tokenIndex = _findTokenIndex(loc, tokens.m_tokens.getBuffer(), tokens.m_tokens.getCount()); + Index tokenIndex = + _findTokenIndex(loc, tokens.m_tokens.getBuffer(), tokens.m_tokens.getCount()); if (tokenIndex >= 0 && lineIndex >= 0) { FindInfo findInfo; @@ -885,7 +955,6 @@ SlangResult DocMarkupExtractor::extract(const SearchItemInput* inputs, Index inp // Save the extracted text in the output dst.text = buf; - } else if (res != SLANG_E_NOT_FOUND) { diff --git a/source/compiler-core/slang-doc-extractor.h b/source/compiler-core/slang-doc-extractor.h index 30346ce6f..45575126f 100644 --- a/source/compiler-core/slang-doc-extractor.h +++ b/source/compiler-core/slang-doc-extractor.h @@ -3,25 +3,25 @@ #define SLANG_DOC_EXTRACTOR_H #include "../core/slang-basic.h" - -#include "slang-source-loc.h" #include "slang-lexer.h" +#include "slang-source-loc.h" -namespace Slang { +namespace Slang +{ enum class MarkupVisibility : uint8_t { - Public, ///< Always available - Internal, ///< Can be available in more verbose 'internal' documentation - Hidden, ///< Not generally available + Public, ///< Always available + Internal, ///< Can be available in more verbose 'internal' documentation + Hidden, ///< Not generally available }; -/* Extracts 'markup' from comments in Slang source core. The comments are extracted and associated in declarations. The association -is held in DocMarkup type. The comment style follows the doxygen style */ +/* Extracts 'markup' from comments in Slang source core. The comments are extracted and associated +in declarations. The association is held in DocMarkup type. The comment style follows the doxygen +style */ class DocMarkupExtractor { public: - typedef uint32_t MarkupFlags; struct MarkupFlag { @@ -29,8 +29,8 @@ public: { Before = 0x1, After = 0x2, - IsMultiToken = 0x4, ///< Can use more than one token - IsBlock = 0x8, ///< + IsMultiToken = 0x4, ///< Can use more than one token + IsBlock = 0x8, ///< }; }; @@ -39,20 +39,23 @@ public: { None, - BlockBefore, /// /** */ or /*! */. - LineBangBefore, /// //! Can be multiple lines - LineSlashBefore, /// /// Can be multiple lines + BlockBefore, /// /** */ or /*! */. + LineBangBefore, /// //! Can be multiple lines + LineSlashBefore, /// /// Can be multiple lines OrdinaryBlockBefore, OrdinaryLineBefore, - BlockAfter, /// /*!< */ or /**< */ - LineBangAfter, /// //!< Can be multiple lines - LineSlashAfter, /// ///< Can be multiple lines + BlockAfter, /// /*!< */ or /**< */ + LineBangAfter, /// //!< Can be multiple lines + LineSlashAfter, /// ///< Can be multiple lines OrdinaryLineAfter, - }; - static bool isBefore(MarkupType type) { return Index(type) >= Index(MarkupType::BlockBefore) && Index(type) <= Index(MarkupType::OrdinaryLineBefore); } + static bool isBefore(MarkupType type) + { + return Index(type) >= Index(MarkupType::BlockBefore) && + Index(type) <= Index(MarkupType::OrdinaryLineBefore); + } static bool isAfter(MarkupType type) { return Index(type) >= Index(MarkupType::BlockAfter); } struct IndexRange @@ -65,15 +68,18 @@ public: enum class Location { - None, ///< No defined location + None, ///< No defined location Before, - AfterParam, ///< Can have trailing , or ) - AfterSemicolon, ///< Can have a trailing ; - AfterEnumCase, ///< Can have a , or before } - AfterGenericParam, ///< Can have trailing , or > + AfterParam, ///< Can have trailing , or ) + AfterSemicolon, ///< Can have a trailing ; + AfterEnumCase, ///< Can have a , or before } + AfterGenericParam, ///< Can have trailing , or > }; - static bool isAfter(Location location) { return Index(location) >= Index(Location::AfterParam); } + static bool isAfter(Location location) + { + return Index(location) >= Index(Location::AfterParam); + } static bool isBefore(Location location) { return location == Location::Before; } struct FoundMarkup @@ -82,7 +88,7 @@ public: { location = Location::None; type = MarkupType::None; - range = IndexRange{ 0, 0 }; + range = IndexRange{0, 0}; } Location location = Location::None; @@ -92,50 +98,54 @@ public: enum SearchStyle { - None, ///< Cannot be searched for - EnumCase, ///< An enum case - Param, ///< A parameter in a function/method - Variable, ///< A variable-like declaration - Before, ///< Only allows before - Function, ///< Function/method - GenericParam, ///< Generic parameter - Attribute, ///< Attribute definition + None, ///< Cannot be searched for + EnumCase, ///< An enum case + Param, ///< A parameter in a function/method + Variable, ///< A variable-like declaration + Before, ///< Only allows before + Function, ///< Function/method + GenericParam, ///< Generic parameter + Attribute, ///< Attribute definition }; - /// An input search item + /// An input search item struct SearchItemInput { SourceLoc sourceLoc; - SearchStyle searchStyle; ///< The search style when looking for an item + SearchStyle searchStyle; ///< The search style when looking for an item }; - /// The items will be in source order + /// The items will be in source order struct SearchItemOutput { - Index viewIndex; ///< Index into the array of views on the output - Index inputIndex; ///< The index to this item in the input - String text; ///< The found text - MarkupVisibility visibilty; ///< Visibility of the item + Index viewIndex; ///< Index into the array of views on the output + Index inputIndex; ///< The index to this item in the input + String text; ///< The found text + MarkupVisibility visibilty; ///< Visibility of the item }; struct FindInfo { - SourceView* sourceView; ///< The source view the tokens were generated from - TokenList* tokenList; ///< The token list - Index tokenIndex; ///< The token index location (where searches start from) - Index lineIndex; ///< The line number for the decl + SourceView* sourceView; ///< The source view the tokens were generated from + TokenList* tokenList; ///< The token list + Index tokenIndex; ///< The token index location (where searches start from) + Index lineIndex; ///< The line number for the decl }; - void setSearchInOrdinaryComments(bool val) - { - m_searchInOrindaryComments = val; - } - - /// Extracts 'markup' doc information for the specified input items - /// The output is placed in out - with the items now in the source order *not* the order of the input items - /// The inputIndex on the output holds the input item index - /// The outViews holds the views specified in viewIndex in the output, which may be useful for determining where the documentation was placed in source - SlangResult extract(const SearchItemInput* inputItems, Index inputCount, SourceManager* sourceManager, DiagnosticSink* sink, List& outViews, List& out); + void setSearchInOrdinaryComments(bool val) { m_searchInOrindaryComments = val; } + + /// Extracts 'markup' doc information for the specified input items + /// The output is placed in out - with the items now in the source order *not* the order of the + /// input items The inputIndex on the output holds the input item index The outViews holds the + /// views specified in viewIndex in the output, which may be useful for determining where the + /// documentation was placed in source + SlangResult extract( + const SearchItemInput* inputItems, + Index inputCount, + SourceManager* sourceManager, + DiagnosticSink* sink, + List& outViews, + List& out); static MarkupFlags getFlags(MarkupType type); static MarkupType findMarkupType(const Token& tok); @@ -145,24 +155,42 @@ protected: /// returns SLANG_E_NOT_FOUND if not found, SLANG_OK on success else an error SlangResult _findMarkup(const FindInfo& info, Location location, FoundMarkup& out); - /// Locations are processed in order, and the first successful used. If found in another location will issue a warning. - /// returns SLANG_E_NOT_FOUND if not found, SLANG_OK on success else an error - SlangResult _findFirstMarkup(const FindInfo& info, const Location* locs, Index locCount, FoundMarkup& out, Index& outIndex); - - SlangResult _findMarkup(const FindInfo& info, const Location* locs, Index locCount, FoundMarkup& out); - - /// Given the decl, the token stream, and the decls tokenIndex, try to find some associated markup + /// Locations are processed in order, and the first successful used. If found in another + /// location will issue a warning. returns SLANG_E_NOT_FOUND if not found, SLANG_OK on success + /// else an error + SlangResult _findFirstMarkup( + const FindInfo& info, + const Location* locs, + Index locCount, + FoundMarkup& out, + Index& outIndex); + + SlangResult _findMarkup( + const FindInfo& info, + const Location* locs, + Index locCount, + FoundMarkup& out); + + /// Given the decl, the token stream, and the decls tokenIndex, try to find some associated + /// markup SlangResult _findMarkup(const FindInfo& info, SearchStyle searchStyle, FoundMarkup& out); /// Given a found markup location extracts the contents of the tokens into out - SlangResult _extractMarkup(const FindInfo& info, const FoundMarkup& foundMarkup, StringBuilder& out); + SlangResult _extractMarkup( + const FindInfo& info, + const FoundMarkup& foundMarkup, + StringBuilder& out); /// Given a location, try to find the first token index that could potentially be markup /// Will return -1 if not found Index _findStartIndex(const FindInfo& info, Location location); /// True if the tok is 'on' lineIndex. Interpretation of 'on' depends on the markup type. - static bool _isTokenOnLineIndex(SourceView* sourceView, MarkupType type, const Token& tok, Index lineIndex); + static bool _isTokenOnLineIndex( + SourceView* sourceView, + MarkupType type, + const Token& tok, + Index lineIndex); DiagnosticSink* m_sink; diff --git a/source/compiler-core/slang-downstream-compiler-set.cpp b/source/compiler-core/slang-downstream-compiler-set.cpp index ee09b994c..151c74b3e 100644 --- a/source/compiler-core/slang-downstream-compiler-set.cpp +++ b/source/compiler-core/slang-downstream-compiler-set.cpp @@ -19,7 +19,7 @@ Index DownstreamCompilerSet::_findIndex(const DownstreamCompilerDesc& desc) cons { const Index count = m_compilers.getCount(); for (Index i = 0; i < count; ++i) - { + { if (m_compilers[i]->getDesc() == desc) { return i; @@ -28,7 +28,8 @@ Index DownstreamCompilerSet::_findIndex(const DownstreamCompilerDesc& desc) cons return -1; } -IDownstreamCompiler* DownstreamCompilerSet::getCompiler(const DownstreamCompilerDesc& compilerDesc) const +IDownstreamCompiler* DownstreamCompilerSet::getCompiler( + const DownstreamCompilerDesc& compilerDesc) const { const Index index = _findIndex(compilerDesc); return index >= 0 ? m_compilers[index] : nullptr; @@ -37,13 +38,14 @@ IDownstreamCompiler* DownstreamCompilerSet::getCompiler(const DownstreamCompiler void DownstreamCompilerSet::getCompilers(List& outCompilers) const { outCompilers.clear(); - outCompilers.addRange((IDownstreamCompiler*const*)m_compilers.begin(), m_compilers.getCount()); + outCompilers.addRange((IDownstreamCompiler* const*)m_compilers.begin(), m_compilers.getCount()); } bool DownstreamCompilerSet::hasSharedLibrary(ISlangSharedLibrary* lib) { - const Index foundIndex = m_sharedLibraries.findFirstIndex([lib](ISlangSharedLibrary* inLib) -> bool { return lib == inLib; }); - return(foundIndex >= 0); + const Index foundIndex = m_sharedLibraries.findFirstIndex( + [lib](ISlangSharedLibrary* inLib) -> bool { return lib == inLib; }); + return (foundIndex >= 0); } void DownstreamCompilerSet::addSharedLibrary(ISlangSharedLibrary* lib) @@ -94,4 +96,4 @@ void DownstreamCompilerSet::addCompiler(IDownstreamCompiler* compiler) } } -} +} // namespace Slang diff --git a/source/compiler-core/slang-downstream-compiler-set.h b/source/compiler-core/slang-downstream-compiler-set.h index 2a3d1ac01..042fcc9f6 100644 --- a/source/compiler-core/slang-downstream-compiler-set.h +++ b/source/compiler-core/slang-downstream-compiler-set.h @@ -11,23 +11,29 @@ class DownstreamCompilerSet : public RefObject public: typedef RefObject Super; - /// Find all the available compilers + /// Find all the available compilers void getCompilerDescs(List& outCompilerDescs) const; - /// Returns list of all compilers + /// Returns list of all compilers void getCompilers(List& outCompilers) const; - /// Get a compiler + /// Get a compiler IDownstreamCompiler* getCompiler(const DownstreamCompilerDesc& compilerDesc) const; - - /// Will replace if there is one with same desc + + /// Will replace if there is one with same desc void addCompiler(IDownstreamCompiler* compiler); - /// Get a default compiler - IDownstreamCompiler* getDefaultCompiler(SlangSourceLanguage sourceLanguage) const { return m_defaultCompilers[int(sourceLanguage)]; } - /// Set the default compiler - void setDefaultCompiler(SlangSourceLanguage sourceLanguage, IDownstreamCompiler* compiler) { m_defaultCompilers[int(sourceLanguage)] = compiler; } + /// Get a default compiler + IDownstreamCompiler* getDefaultCompiler(SlangSourceLanguage sourceLanguage) const + { + return m_defaultCompilers[int(sourceLanguage)]; + } + /// Set the default compiler + void setDefaultCompiler(SlangSourceLanguage sourceLanguage, IDownstreamCompiler* compiler) + { + m_defaultCompilers[int(sourceLanguage)] = compiler; + } - /// True if has a compiler of the specified type + /// True if has a compiler of the specified type bool hasCompiler(SlangPassThrough compilerType) const; void remove(SlangPassThrough compilerType); @@ -51,7 +57,6 @@ public: } protected: - Index _findIndex(const DownstreamCompilerDesc& desc) const; @@ -63,6 +68,6 @@ protected: List> m_sharedLibraries; }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-downstream-compiler-util.cpp b/source/compiler-core/slang-downstream-compiler-util.cpp index bf4c7cc04..1ab35d4fe 100644 --- a/source/compiler-core/slang-downstream-compiler-util.cpp +++ b/source/compiler-core/slang-downstream-compiler-util.cpp @@ -1,30 +1,28 @@ // slang-downstream-compiler.cpp #include "slang-downstream-compiler-util.h" +#include "../core/slang-blob.h" +#include "../core/slang-char-util.h" #include "../core/slang-common.h" -#include "slang-com-helper.h" -#include "../core/slang-string-util.h" - -#include "../core/slang-type-text-util.h" - #include "../core/slang-io.h" #include "../core/slang-shared-library.h" -#include "../core/slang-blob.h" -#include "../core/slang-char-util.h" +#include "../core/slang-string-util.h" +#include "../core/slang-type-text-util.h" +#include "slang-com-helper.h" #ifdef SLANG_VC -# include "windows/slang-win-visual-studio-util.h" +#include "windows/slang-win-visual-studio-util.h" #endif -#include "slang-visual-studio-compiler-util.h" -#include "slang-gcc-compiler-util.h" -#include "slang-nvrtc-compiler.h" -#include "slang-fxc-compiler.h" #include "slang-dxc-compiler.h" +#include "slang-fxc-compiler.h" +#include "slang-gcc-compiler-util.h" #include "slang-glslang-compiler.h" #include "slang-llvm-compiler.h" #include "slang-metal-compiler.h" +#include "slang-nvrtc-compiler.h" #include "slang-tint-compiler.h" +#include "slang-visual-studio-compiler-util.h" namespace Slang { @@ -46,10 +44,14 @@ struct DownstreamCompilerInfos DownstreamCompilerInfos infos; - infos.infos[int(SLANG_PASS_THROUGH_CLANG)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); - infos.infos[int(SLANG_PASS_THROUGH_VISUAL_STUDIO)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); - infos.infos[int(SLANG_PASS_THROUGH_GCC)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); - infos.infos[int(SLANG_PASS_THROUGH_LLVM)] = Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); + infos.infos[int(SLANG_PASS_THROUGH_CLANG)] = + Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); + infos.infos[int(SLANG_PASS_THROUGH_VISUAL_STUDIO)] = + Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); + infos.infos[int(SLANG_PASS_THROUGH_GCC)] = + Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); + infos.infos[int(SLANG_PASS_THROUGH_LLVM)] = + Info(SourceLanguageFlag::CPP | SourceLanguageFlag::C); infos.infos[int(SLANG_PASS_THROUGH_NVRTC)] = Info(SourceLanguageFlag::CUDA); @@ -61,16 +63,20 @@ struct DownstreamCompilerInfos return infos; } -/* static */DownstreamCompilerInfos DownstreamCompilerInfos::s_infos = DownstreamCompilerInfos::_calcInfos(); +/* static */ DownstreamCompilerInfos DownstreamCompilerInfos::s_infos = + DownstreamCompilerInfos::_calcInfos(); /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerInfo !!!!!!!!!!!!!!!!!!!!!!*/ -/* static */const DownstreamCompilerInfo& DownstreamCompilerInfo::getInfo(SlangPassThrough compiler) +/* static */ const DownstreamCompilerInfo& DownstreamCompilerInfo::getInfo( + SlangPassThrough compiler) { return DownstreamCompilerInfos::s_infos.infos[int(compiler)]; } -/* static */bool DownstreamCompilerInfo::canCompile(SlangPassThrough compiler, SlangSourceLanguage sourceLanguage) +/* static */ bool DownstreamCompilerInfo::canCompile( + SlangPassThrough compiler, + SlangSourceLanguage sourceLanguage) { const auto& info = getInfo(compiler); return (info.sourceLanguageFlags & (SourceLanguageFlags(1) << int(sourceLanguage))) != 0; @@ -91,7 +97,8 @@ static DownstreamCompilerMatchVersion _calcCompiledVersion() matchVersion.type = SLANG_PASS_THROUGH_GCC; matchVersion.matchVersion.set(Index(__GNUC__), Index(__GNUC_MINOR__)); #else - // TODO(JS): Hmmm None is not quite the same as unknown. It works for now, but we might want to have a distinct enum for unknown. + // TODO(JS): Hmmm None is not quite the same as unknown. It works for now, but we might want to + // have a distinct enum for unknown. matchVersion.type = SLANG_PASS_THROUGH_NONE; #endif @@ -105,14 +112,20 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() return s_version; } -/* static */IDownstreamCompiler* DownstreamCompilerUtil::findCompiler(const DownstreamCompilerSet* set, MatchType matchType, const DownstreamCompilerDesc& desc) +/* static */ IDownstreamCompiler* DownstreamCompilerUtil::findCompiler( + const DownstreamCompilerSet* set, + MatchType matchType, + const DownstreamCompilerDesc& desc) { List compilers; set->getCompilers(compilers); return findCompiler(compilers, matchType, desc); } -/* static */IDownstreamCompiler* DownstreamCompilerUtil::findCompiler(const List& compilers, MatchType matchType, const DownstreamCompilerDesc& desc) +/* static */ IDownstreamCompiler* DownstreamCompilerUtil::findCompiler( + const List& compilers, + MatchType matchType, + const DownstreamCompilerDesc& desc) { if (compilers.getCount() <= 0) { @@ -145,7 +158,7 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() const Int versionValue = compilerDesc.getVersionValue(); switch (matchType) { - case MatchType::MinGreaterEqual: + case MatchType::MinGreaterEqual: { auto diff = descVersionValue - versionValue; if (diff >= 0 && diff < minVersionDiff) @@ -155,7 +168,7 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() } break; } - case MatchType::MinAbsolute: + case MatchType::MinAbsolute: { auto diff = descVersionValue - versionValue; diff = (diff >= 0) ? diff : -diff; @@ -166,7 +179,7 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() } break; } - case MatchType::Newest: + case MatchType::Newest: { if (versionValue > maxVersionValue) { @@ -182,7 +195,9 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() return (bestIndex >= 0) ? compilers[bestIndex] : nullptr; } -/* static */IDownstreamCompiler* DownstreamCompilerUtil::findCompiler(const List& compilers, const DownstreamCompilerDesc& desc) +/* static */ IDownstreamCompiler* DownstreamCompilerUtil::findCompiler( + const List& compilers, + const DownstreamCompilerDesc& desc) { for (auto compiler : compilers) { @@ -194,15 +209,21 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() return nullptr; } -/* static */IDownstreamCompiler* DownstreamCompilerUtil::findCompiler(const List& compilers, SlangPassThrough type, const SemanticVersion& version) +/* static */ IDownstreamCompiler* DownstreamCompilerUtil::findCompiler( + const List& compilers, + SlangPassThrough type, + const SemanticVersion& version) { DownstreamCompilerDesc desc; desc.type = type; - desc.version = version; + desc.version = version; return findCompiler(compilers, desc); } -/* static */void DownstreamCompilerUtil::findVersions(const List& compilers, SlangPassThrough type, List& outVersions) +/* static */ void DownstreamCompilerUtil::findVersions( + const List& compilers, + SlangPassThrough type, + List& outVersions) { for (auto compiler : compilers) { @@ -215,7 +236,9 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() } } -/* static */IDownstreamCompiler* DownstreamCompilerUtil::findClosestCompiler(const List& compilers, const DownstreamCompilerMatchVersion& matchVersion) +/* static */ IDownstreamCompiler* DownstreamCompilerUtil::findClosestCompiler( + const List& compilers, + const DownstreamCompilerMatchVersion& matchVersion) { List versions; @@ -230,7 +253,10 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() } // Okay lets find the best one - auto bestVersion = MatchSemanticVersion::findAnyBest(versions.getBuffer(), versions.getCount(), matchVersion.matchVersion); + auto bestVersion = MatchSemanticVersion::findAnyBest( + versions.getBuffer(), + versions.getCount(), + matchVersion.matchVersion); // If one is found use it if (bestVersion.isSet()) @@ -241,14 +267,13 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() { // TODO(JS): - // NOTE! This may not really be appropriate, because LLVM is *not* interchangable with + // NOTE! This may not really be appropriate, because LLVM is *not* interchangable with // a 'normal' C++ compiler as cannot access standard libraries/headers. // So `slang-llvm` can't be used for 'host' code. - // These compilers should be usable interchangably. The order is important, as the first one that matches will - // be used, so LLVM is used before CLANG or GCC if appropriate - const SlangPassThrough compatiblePassThroughs[] = - { + // These compilers should be usable interchangably. The order is important, as the first one + // that matches will be used, so LLVM is used before CLANG or GCC if appropriate + const SlangPassThrough compatiblePassThroughs[] = { SLANG_PASS_THROUGH_LLVM, SLANG_PASS_THROUGH_CLANG, SLANG_PASS_THROUGH_GCC, @@ -266,7 +291,8 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() if (versions.getCount() > 0) { // Get the latest version (as we have no way to really compare) - auto latestVersion = SemanticVersion::getLatest(versions.getBuffer(), versions.getCount()); + auto latestVersion = + SemanticVersion::getLatest(versions.getBuffer(), versions.getCount()); return findCompiler(compilers, matchVersion.type, latestVersion); } } @@ -276,21 +302,25 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() return nullptr; } -/* static */IDownstreamCompiler* DownstreamCompilerUtil::findClosestCompiler(const DownstreamCompilerSet* set, const DownstreamCompilerMatchVersion& matchVersion) +/* static */ IDownstreamCompiler* DownstreamCompilerUtil::findClosestCompiler( + const DownstreamCompilerSet* set, + const DownstreamCompilerMatchVersion& matchVersion) { List compilers; set->getCompilers(compilers); return findClosestCompiler(compilers, matchVersion); } -/* static */void DownstreamCompilerUtil::updateDefault(DownstreamCompilerSet* set, SlangSourceLanguage sourceLanguage) +/* static */ void DownstreamCompilerUtil::updateDefault( + DownstreamCompilerSet* set, + SlangSourceLanguage sourceLanguage) { IDownstreamCompiler* compiler = nullptr; switch (sourceLanguage) { - case SLANG_SOURCE_LANGUAGE_CPP: - case SLANG_SOURCE_LANGUAGE_C: + case SLANG_SOURCE_LANGUAGE_CPP: + case SLANG_SOURCE_LANGUAGE_C: { // Find the compiler closest to the compiler this was compiled with if (!compiler) @@ -299,20 +329,20 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() } break; } - case SLANG_SOURCE_LANGUAGE_CUDA: + case SLANG_SOURCE_LANGUAGE_CUDA: { DownstreamCompilerDesc desc; desc.type = SLANG_PASS_THROUGH_NVRTC; compiler = findCompiler(set, MatchType::Newest, desc); break; } - default: break; + default: break; } set->setDefaultCompiler(sourceLanguage, compiler); } -/* static */void DownstreamCompilerUtil::updateDefaults(DownstreamCompilerSet* set) +/* static */ void DownstreamCompilerUtil::updateDefaults(DownstreamCompilerSet* set) { for (Index i = 0; i < Index(SLANG_SOURCE_LANGUAGE_COUNT_OF); ++i) { @@ -320,7 +350,8 @@ DownstreamCompilerMatchVersion DownstreamCompilerUtil::getCompiledVersion() } } -/* static */void DownstreamCompilerUtil::setDefaultLocators(DownstreamCompilerLocatorFunc outFuncs[int(SLANG_PASS_THROUGH_COUNT_OF)]) +/* static */ void DownstreamCompilerUtil::setDefaultLocators( + DownstreamCompilerLocatorFunc outFuncs[int(SLANG_PASS_THROUGH_COUNT_OF)]) { outFuncs[int(SLANG_PASS_THROUGH_VISUAL_STUDIO)] = &VisualStudioCompilerUtil::locateCompilers; outFuncs[int(SLANG_PASS_THROUGH_CLANG)] = &GCCDownstreamCompilerUtil::locateClangCompilers; @@ -350,7 +381,11 @@ static String _getParentPath(const String& path) } } -static SlangResult _findPaths(const String& path, const char* libraryName, String& outParentPath, String& outLibraryPath) +static SlangResult _findPaths( + const String& path, + const char* libraryName, + String& outParentPath, + String& outLibraryPath) { // Try to determine what the path is by looking up the path type SlangPathType pathType; @@ -372,14 +407,17 @@ static SlangResult _findPaths(const String& path, const char* libraryName, Strin return SLANG_OK; } - // If this failed the path could be to a shared library, but we may need to convert to the shared library filename first + // If this failed the path could be to a shared library, but we may need to convert to the + // shared library filename first const String sharedLibraryFilePath = SharedLibrary::calcPlatformPath(path.getUnownedSlice()); - if (SLANG_SUCCEEDED(Path::getPathType(sharedLibraryFilePath, &pathType)) && pathType == SLANG_PATH_TYPE_FILE) + if (SLANG_SUCCEEDED(Path::getPathType(sharedLibraryFilePath, &pathType)) && + pathType == SLANG_PATH_TYPE_FILE) { - // We pass in the shared library path, as canonical paths can sometimes only apply to pre-existing objects. + // We pass in the shared library path, as canonical paths can sometimes only apply to + // pre-existing objects. outParentPath = _getParentPath(sharedLibraryFilePath); - // The original path should work as is for the SharedLibrary load. Notably we don't use the sharedLibraryFilePath - // as this is the wrong name to do a SharedLibrary load with. + // The original path should work as is for the SharedLibrary load. Notably we don't use the + // sharedLibraryFilePath as this is the wrong name to do a SharedLibrary load with. outLibraryPath = path; return SLANG_OK; @@ -388,7 +426,12 @@ static SlangResult _findPaths(const String& path, const char* libraryName, Strin return SLANG_FAIL; } -/* static */SlangResult DownstreamCompilerUtil::loadSharedLibrary(const String& path, ISlangSharedLibraryLoader* loader, const char*const* dependentNames, const char* inLibraryName, ComPtr& outSharedLib) +/* static */ SlangResult DownstreamCompilerUtil::loadSharedLibrary( + const String& path, + ISlangSharedLibraryLoader* loader, + const char* const* dependentNames, + const char* inLibraryName, + ComPtr& outSharedLib) { String parentPath; String libraryPath; @@ -399,19 +442,21 @@ static SlangResult _findPaths(const String& path, const char* libraryName, Strin if (SLANG_FAILED(_findPaths(path, inLibraryName, parentPath, libraryPath))) { // We have a few scenarios here. - // 1) The path could be the shared library/dll filename, that will be found through some operating system mechanism - // 2) That the shared library is *NOT* on the filesystem directly (the loader does something different) - // 3) Permissions or some other mechanism stops the lookup from working + // 1) The path could be the shared library/dll filename, that will be found through some + // operating system mechanism 2) That the shared library is *NOT* on the filesystem + // directly (the loader does something different) 3) Permissions or some other mechanism + // stops the lookup from working // We should probably assume that the path means something, else why set it. - // It's probably less likely that it is a directory that we can't detect - as if it's a directory as part of an app - // it's permissions should allow detection, or be made to allow it. + // It's probably less likely that it is a directory that we can't detect - as if it's a + // directory as part of an app it's permissions should allow detection, or be made to + // allow it. // All this being the case we should probably assume that it is the shared library name. libraryPath = path; - // Attempt to get a parent. If there isn't one this will be empty, which will mean it will be ignored, which is probably - // what we want if path is just a shared library name + // Attempt to get a parent. If there isn't one this will be empty, which will mean it + // will be ignored, which is probably what we want if path is just a shared library name parentPath = Path::getParentDirectory(libraryPath); } } @@ -422,7 +467,7 @@ static SlangResult _findPaths(const String& path, const char* libraryName, Strin // Try to load any dependent libs from the parent path if (dependentNames) { - for (const char*const* cur = dependentNames; *cur; ++cur) + for (const char* const* cur = dependentNames; *cur; ++cur) { const char* dependentName = *cur; ComPtr lib; @@ -455,7 +500,9 @@ static SlangResult _findPaths(const String& path, const char* libraryName, Strin } } -/* static */void DownstreamCompilerUtil::appendAsText(const DownstreamCompilerDesc& desc, StringBuilder& out) +/* static */ void DownstreamCompilerUtil::appendAsText( + const DownstreamCompilerDesc& desc, + StringBuilder& out) { out << TypeTextUtil::getPassThroughAsHumanText(desc.type); @@ -469,4 +516,4 @@ static SlangResult _findPaths(const String& path, const char* libraryName, Strin } } -} +} // namespace Slang diff --git a/source/compiler-core/slang-downstream-compiler-util.h b/source/compiler-core/slang-downstream-compiler-util.h index 84b8edcca..b6efb2e4f 100644 --- a/source/compiler-core/slang-downstream-compiler-util.h +++ b/source/compiler-core/slang-downstream-compiler-util.h @@ -1,13 +1,16 @@ #ifndef SLANG_DOWNSTREAM_COMPILER_UTIL_H #define SLANG_DOWNSTREAM_COMPILER_UTIL_H -#include "slang-downstream-compiler.h" #include "slang-downstream-compiler-set.h" +#include "slang-downstream-compiler.h" namespace Slang { -typedef SlangResult (*DownstreamCompilerLocatorFunc)(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); +typedef SlangResult (*DownstreamCompilerLocatorFunc)( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); struct DownstreamCompilerInfo { @@ -33,31 +36,38 @@ struct DownstreamCompilerInfo /// True if this compiler can compile the specified language static bool canCompile(SlangPassThrough compiler, SlangSourceLanguage sourceLanguage); - DownstreamCompilerInfo() : sourceLanguageFlags(0) {} + DownstreamCompilerInfo() + : sourceLanguageFlags(0) + { + } - DownstreamCompilerInfo(SourceLanguageFlags inSourceLanguageFlags) : - sourceLanguageFlags(inSourceLanguageFlags) - {} + DownstreamCompilerInfo(SourceLanguageFlags inSourceLanguageFlags) + : sourceLanguageFlags(inSourceLanguageFlags) + { + } SourceLanguageFlags sourceLanguageFlags; }; -// Combination of a downstream compiler type (pass through) and +// Combination of a downstream compiler type (pass through) and // a match version. struct DownstreamCompilerMatchVersion { - DownstreamCompilerMatchVersion(SlangPassThrough inType, MatchSemanticVersion inMatchVersion) : - type(inType), - matchVersion(inMatchVersion) - {} + DownstreamCompilerMatchVersion(SlangPassThrough inType, MatchSemanticVersion inMatchVersion) + : type(inType), matchVersion(inMatchVersion) + { + } - DownstreamCompilerMatchVersion() :type(SLANG_PASS_THROUGH_NONE) {} + DownstreamCompilerMatchVersion() + : type(SLANG_PASS_THROUGH_NONE) + { + } - SlangPassThrough type; ///< The type of the compiler - MatchSemanticVersion matchVersion; ///< The match version + SlangPassThrough type; ///< The type of the compiler + MatchSemanticVersion matchVersion; ///< The match version }; -struct DownstreamCompilerUtil: public DownstreamCompilerUtilBase +struct DownstreamCompilerUtil : public DownstreamCompilerUtilBase { enum class MatchType { @@ -66,40 +76,66 @@ struct DownstreamCompilerUtil: public DownstreamCompilerUtilBase Newest, }; - /// Find a compiler - static IDownstreamCompiler* findCompiler(const DownstreamCompilerSet* set, MatchType matchType, const DownstreamCompilerDesc& desc); - static IDownstreamCompiler* findCompiler(const List& compilers, MatchType matchType, const DownstreamCompilerDesc& desc); - - static IDownstreamCompiler* findCompiler(const List& compilers, SlangPassThrough type, const SemanticVersion& version); - static IDownstreamCompiler* findCompiler(const List& compilers, const DownstreamCompilerDesc& desc); - - /// Find all the compilers with the version - static void findVersions(const List& compilers, SlangPassThrough compiler, List& versions); - - - /// Find the compiler closest to the desc - static IDownstreamCompiler* findClosestCompiler(const List& compilers, const DownstreamCompilerMatchVersion& version); - static IDownstreamCompiler* findClosestCompiler(const DownstreamCompilerSet* set, const DownstreamCompilerMatchVersion& version); - - /// Get the information on the compiler used to compile this source + /// Find a compiler + static IDownstreamCompiler* findCompiler( + const DownstreamCompilerSet* set, + MatchType matchType, + const DownstreamCompilerDesc& desc); + static IDownstreamCompiler* findCompiler( + const List& compilers, + MatchType matchType, + const DownstreamCompilerDesc& desc); + + static IDownstreamCompiler* findCompiler( + const List& compilers, + SlangPassThrough type, + const SemanticVersion& version); + static IDownstreamCompiler* findCompiler( + const List& compilers, + const DownstreamCompilerDesc& desc); + + /// Find all the compilers with the version + static void findVersions( + const List& compilers, + SlangPassThrough compiler, + List& versions); + + + /// Find the compiler closest to the desc + static IDownstreamCompiler* findClosestCompiler( + const List& compilers, + const DownstreamCompilerMatchVersion& version); + static IDownstreamCompiler* findClosestCompiler( + const DownstreamCompilerSet* set, + const DownstreamCompilerMatchVersion& version); + + /// Get the information on the compiler used to compile this source static DownstreamCompilerMatchVersion getCompiledVersion(); static void updateDefault(DownstreamCompilerSet* set, SlangSourceLanguage sourceLanguage); static void updateDefaults(DownstreamCompilerSet* set); - static void setDefaultLocators(DownstreamCompilerLocatorFunc outFuncs[int(SLANG_PASS_THROUGH_COUNT_OF)]); - - /// Attempts to determine what 'path' is and load appropriately. Is it a path to a shared library? Is it a directory holding the libraries? - /// Some downstream shared libraries need other shared libraries to be loaded before the main shared library, such that they are in the same directory - /// otherwise the shared library could come from some unwanted location. - /// dependentNames names shared libraries which should be attempted to be loaded in the path of the main shared library. - /// The list is optional (nullptr can be passed in), and the list is terminated by nullptr. - static SlangResult loadSharedLibrary(const String& path, ISlangSharedLibraryLoader* loader, const char*const* dependantNames, const char* libraryName, ComPtr& outSharedLib); - - /// Append the desc as text + static void setDefaultLocators( + DownstreamCompilerLocatorFunc outFuncs[int(SLANG_PASS_THROUGH_COUNT_OF)]); + + /// Attempts to determine what 'path' is and load appropriately. Is it a path to a shared + /// library? Is it a directory holding the libraries? Some downstream shared libraries need + /// other shared libraries to be loaded before the main shared library, such that they are in + /// the same directory otherwise the shared library could come from some unwanted location. + /// dependentNames names shared libraries which should be attempted to be loaded in the path of + /// the main shared library. The list is optional (nullptr can be passed in), and the list is + /// terminated by nullptr. + static SlangResult loadSharedLibrary( + const String& path, + ISlangSharedLibraryLoader* loader, + const char* const* dependantNames, + const char* libraryName, + ComPtr& outSharedLib); + + /// Append the desc as text static void appendAsText(const DownstreamCompilerDesc& desc, StringBuilder& out); }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-downstream-compiler.cpp b/source/compiler-core/slang-downstream-compiler.cpp index 855319176..190400f55 100644 --- a/source/compiler-core/slang-downstream-compiler.cpp +++ b/source/compiler-core/slang-downstream-compiler.cpp @@ -1,37 +1,36 @@ // slang-downstream-compiler.cpp #include "slang-downstream-compiler.h" +#include "../core/slang-blob.h" +#include "../core/slang-castable.h" +#include "../core/slang-char-util.h" #include "../core/slang-common.h" -#include "slang-com-helper.h" -#include "../core/slang-string-util.h" - -#include "../core/slang-type-text-util.h" - #include "../core/slang-io.h" #include "../core/slang-shared-library.h" -#include "../core/slang-blob.h" -#include "../core/slang-char-util.h" - -#include "../core/slang-castable.h" - +#include "../core/slang-string-util.h" +#include "../core/slang-type-text-util.h" +#include "slang-artifact-associated-impl.h" +#include "slang-artifact-desc-util.h" +#include "slang-artifact-helper.h" #include "slang-artifact-impl.h" #include "slang-artifact-representation-impl.h" -#include "slang-artifact-associated-impl.h" #include "slang-artifact-util.h" -#include "slang-artifact-helper.h" -#include "slang-artifact-desc-util.h" +#include "slang-com-helper.h" namespace Slang { /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! DownstreamCompilerBase !!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ -SlangResult DownstreamCompilerBase::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) +SlangResult DownstreamCompilerBase::convert( + IArtifact* from, + const ArtifactDesc& to, + IArtifact** outArtifact) { SLANG_UNUSED(from); SLANG_UNUSED(to); SLANG_UNUSED(outArtifact); - + return SLANG_E_NOT_AVAILABLE; } @@ -46,8 +45,7 @@ void* DownstreamCompilerBase::castAs(const Guid& guid) void* DownstreamCompilerBase::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IDownstreamCompiler::getTypeGuid()) { return static_cast(this); @@ -64,7 +62,9 @@ void* DownstreamCompilerBase::getObject(const Guid& guid) /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CommandLineDownstreamCompiler !!!!!!!!!!!!!!!!!!!!!!*/ -SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptions, IArtifact** outArtifact) +SlangResult CommandLineDownstreamCompiler::compile( + const CompileOptions& inOptions, + IArtifact** outArtifact) { if (!isVersionCompatible(inOptions)) { @@ -77,11 +77,11 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio // Copy the command line options CommandLine cmdLine(m_cmdLine); - // Work out the ArtifactDesc + // Work out the ArtifactDesc const auto targetDesc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType); auto helper = DefaultArtifactHelper::getSingleton(); - + List> artifactList; // It may be necessary to produce a temporary file 'lock file'. @@ -93,11 +93,13 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio // If no module path is set we will need to generate one if (options.modulePath.count == 0) { - // We could use the path to the source, or use the source name/paths as defined on the artifact - // For now we just go with a lock file based on "slang-generated". - SLANG_RETURN_ON_FAIL(helper->createLockFile(asCharSlice(toSlice("slang-generated")), lockFile.writeRef())); + // We could use the path to the source, or use the source name/paths as defined on the + // artifact For now we just go with a lock file based on "slang-generated". + SLANG_RETURN_ON_FAIL( + helper->createLockFile(asCharSlice(toSlice("slang-generated")), lockFile.writeRef())); - auto lockArtifact = Artifact::create(ArtifactDesc::make(ArtifactKind::Base, ArtifactPayload::Lock, ArtifactStyle::None)); + auto lockArtifact = Artifact::create( + ArtifactDesc::make(ArtifactKind::Base, ArtifactPayload::Lock, ArtifactStyle::None)); lockArtifact->addRepresentation(lockFile); artifactList.add(lockArtifact); @@ -108,14 +110,17 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio options.modulePath = SliceUtil::asTerminatedCharSlice(modulePath); } - // Append command line args to the end of cmdLine using the target specific function for the specified options + // Append command line args to the end of cmdLine using the target specific function for the + // specified options SLANG_RETURN_ON_FAIL(calcArgs(options, cmdLine)); - // The 'productArtifact' is the main product produced from the compilation - the executable/sharedlibrary/object etc + // The 'productArtifact' is the main product produced from the compilation - the + // executable/sharedlibrary/object etc ComPtr productArtifact; { List> artifacts; - SLANG_RETURN_ON_FAIL(calcCompileProducts(options, DownstreamProductFlag::All, lockFile, artifacts)); + SLANG_RETURN_ON_FAIL( + calcCompileProducts(options, DownstreamProductFlag::All, lockFile, artifacts)); for (IArtifact* artifact : artifacts) { @@ -129,7 +134,7 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio artifactList.add(ComPtr(artifact)); } } - + SLANG_ASSERT(productArtifact); // Somethings gone wrong if we don't find the main artifact if (!productArtifact) @@ -155,21 +160,22 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio } #endif - // Go through the list of artifacts in the artifactList and check if they exist. - // - // This is useful because `calcCompileProducts` is conservative and may produce artifacts for products that aren't actually - // produced, by the compilation. + // Go through the list of artifacts in the artifactList and check if they exist. + // + // This is useful because `calcCompileProducts` is conservative and may produce artifacts for + // products that aren't actually produced, by the compilation. { - + Count count = artifactList.getCount(); for (Index i = 0; i < count; ++i) { IArtifact* artifact = artifactList[i]; - + if (!artifact->exists()) { // We should find a file rep and if we do we can disown it. Disowning will mean - // when scope is lost the rep won't try and delete the (apparently non existing) backing file. + // when scope is lost the rep won't try and delete the (apparently non existing) + // backing file. if (auto fileRep = findRepresentation(artifact)) { fileRep->disown(); @@ -189,7 +195,8 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio } } - // Add all of the source artifacts, that are temporary on the file system, such that they can stay in scope for debugging + // Add all of the source artifacts, that are temporary on the file system, such that they can + // stay in scope for debugging for (auto sourceArtifact : options.sourceArtifacts) { if (auto fileRep = findRepresentation(sourceArtifact)) @@ -205,16 +212,18 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio // Create the result artifact auto artifact = ArtifactUtil::createArtifact(targetDesc); - // Createa the diagnostics + // Createa the diagnostics auto diagnostics = ArtifactDiagnostics::create(); SLANG_RETURN_ON_FAIL(parseOutput(exeRes, diagnostics)); ArtifactUtil::addAssociated(artifact, diagnostics); - // Find the rep from the 'main' artifact, we'll just use the same representation on the output + // Find the rep from the 'main' artifact, we'll just use the same representation on the output // artifact. Sharing is desirable, because the rep owns the file. - if (auto fileRep = productArtifact ? findRepresentation(productArtifact) : nullptr) + if (auto fileRep = productArtifact + ? findRepresentation(productArtifact) + : nullptr) { artifact->addRepresentation(fileRep); } @@ -222,13 +231,17 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio // Add the artifact list if there is anything in it if (artifactList.getCount()) { - // Holds all of the artifacts that are relatated to the final artifact - such as debug files, ancillary file and lock files - auto artifactContainer = ArtifactUtil::createArtifact(ArtifactDesc::make(ArtifactKind::Container, ArtifactPayload::Unknown, ArtifactStyle::Unknown)); + // Holds all of the artifacts that are relatated to the final artifact - such as debug + // files, ancillary file and lock files + auto artifactContainer = ArtifactUtil::createArtifact(ArtifactDesc::make( + ArtifactKind::Container, + ArtifactPayload::Unknown, + ArtifactStyle::Unknown)); auto slice = SliceUtil::asSlice(artifactList); artifactContainer->setChildren(slice.data, slice.count); - + artifact->addAssociated(artifactContainer); } @@ -236,4 +249,4 @@ SlangResult CommandLineDownstreamCompiler::compile(const CompileOptions& inOptio return SLANG_OK; } -} +} // namespace Slang diff --git a/source/compiler-core/slang-downstream-compiler.h b/source/compiler-core/slang-downstream-compiler.h index 95793eaa3..c0cc868d1 100644 --- a/source/compiler-core/slang-downstream-compiler.h +++ b/source/compiler-core/slang-downstream-compiler.h @@ -2,19 +2,14 @@ #define SLANG_DOWNSTREAM_COMPILER_H #include "../core/slang-common.h" -#include "../core/slang-string.h" - -#include "../core/slang-process-util.h" - +#include "../core/slang-io.h" #include "../core/slang-platform.h" +#include "../core/slang-process-util.h" #include "../core/slang-semantic-version.h" - -#include "../core/slang-io.h" - -#include "slang-com-ptr.h" - -#include "slang-artifact.h" +#include "../core/slang-string.h" #include "slang-artifact-associated.h" +#include "slang-artifact.h" +#include "slang-com-ptr.h" #include @@ -29,43 +24,58 @@ struct DownstreamCompilerDesc typedef DownstreamCompilerDesc ThisType; HashCode getHashCode() const { return combineHash(HashCode(type), version.getHashCode()); } - bool operator==(const ThisType& rhs) const { return type == rhs.type && version == rhs.version; } + bool operator==(const ThisType& rhs) const + { + return type == rhs.type && version == rhs.version; + } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - /// Get the version as a value + /// Get the version as a value Int getVersionValue() const { return version.m_major * 100 + version.m_minor; } - /// true if has a version set + /// true if has a version set bool hasVersion() const { return version.isSet(); } /// Ctor - explicit DownstreamCompilerDesc(SlangPassThrough inType = SLANG_PASS_THROUGH_NONE, Int inMajorVersion = 0, Int inMinorVersion = 0) :type(inType), version(int(inMajorVersion), int(inMinorVersion)) {} - explicit DownstreamCompilerDesc(SlangPassThrough inType, const SemanticVersion& inVersion) : type(inType), version(inVersion) {} + explicit DownstreamCompilerDesc( + SlangPassThrough inType = SLANG_PASS_THROUGH_NONE, + Int inMajorVersion = 0, + Int inMinorVersion = 0) + : type(inType), version(int(inMajorVersion), int(inMinorVersion)) + { + } + explicit DownstreamCompilerDesc(SlangPassThrough inType, const SemanticVersion& inVersion) + : type(inType), version(inVersion) + { + } - SlangPassThrough type; ///< The type of the compiler - SemanticVersion version; ///< The version of the compiler + SlangPassThrough type; ///< The type of the compiler + SemanticVersion version; ///< The version of the compiler }; -/* Placed at the start of structs that are versioned. -The id uniquely identifies a compatible set of versions. +/* Placed at the start of structs that are versioned. +The id uniquely identifies a compatible set of versions. The size indicates the struct size. It should be considered as a kind of version number. The larger the number for the target the newer the *compatible* version (assuming the identifiers match). -Note that size versioning *only* works, if adding a field *doesn't* use any existing unused "pad" bytes. -This implies that any new members *must* take into account padding/alignment. Any additions that have alignment -*less* than the alignment of struct may need padding. +Note that size versioning *only* works, if adding a field *doesn't* use any existing unused "pad" +bytes. This implies that any new members *must* take into account padding/alignment. Any additions +that have alignment *less* than the alignment of struct may need padding. */ struct VersionedStruct { typedef VersionedStruct ThisType; - VersionedStruct(uint32_t inIdentifier, size_t inSize): - identifier(inIdentifier), - size(uint32_t(inSize)) - {} + VersionedStruct(uint32_t inIdentifier, size_t inSize) + : identifier(inIdentifier), size(uint32_t(inSize)) + { + } - /// True if the versions are identical - bool operator==(const ThisType& rhs) const { return identifier == rhs.identifier && size == rhs.size; } + /// True if the versions are identical + bool operator==(const ThisType& rhs) const + { + return identifier == rhs.identifier && size == rhs.size; + } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } VersionedStruct(const ThisType& rhs) = default; @@ -75,7 +85,7 @@ struct VersionedStruct uint32_t size; }; -template +template T getCompatibleVersion(const T* inT) { const VersionedStruct* in = &inT->version; @@ -85,7 +95,7 @@ T getCompatibleVersion(const T* inT) // Note that the struct is passed in by pointer rather than reference, because // we must ensure that it is not sliced. - + // Must match SLANG_ASSERT(T::kVersionIdentifier == in->identifier); @@ -118,13 +128,13 @@ T getCompatibleVersion(const T* inT) return t; } -template +template bool isVersionCompatible(const VersionedStruct& ver) { return ver.identifier == T::kVersionIdentifier; } -template +template bool isVersionCompatible(const T& in) { return isVersionCompatible(in.version); @@ -132,20 +142,21 @@ bool isVersionCompatible(const T& in) /* Downstream compile options -NOTE! This type is trafficed across shared library boundaries and *versioned*. +NOTE! This type is trafficed across shared library boundaries and *versioned*. In particular * The struct can only contain types that can be trivially memcpyd (checked by static_assert); -* New fields can only be added to the end of the struct -* New fields must take into account alignment/padding such that they do not share bytes in previous version sizes +* New fields can only be added to the end of the struct +* New fields must take into account alignment/padding such that they do not share bytes in previous +version sizes */ struct DownstreamCompileOptions { typedef DownstreamCompileOptions ThisType; - // A unique identifer for this particular struct kind. If the struct become incompatible + // A unique identifer for this particular struct kind. If the struct become incompatible // a new id should be used to identify a specific style. If the change is only to add members - // to the end, this should be handled via the version size at use sites. + // to the end, this should be handled via the version size at use sites. static const uint32_t kVersionIdentifier = 0x34296897; typedef uint32_t Flags; @@ -153,27 +164,31 @@ struct DownstreamCompileOptions { enum Enum : Flags { - EnableExceptionHandling = 0x01, ///< Enables exception handling support (say as optionally supported by C++) - Verbose = 0x02, ///< Give more verbose diagnostics - EnableSecurityChecks = 0x04, ///< Enable runtime security checks (such as for buffer overruns) - enabling typically decreases performance - EnableFloat16 = 0x08, ///< If set compiles with support for float16/half + EnableExceptionHandling = + 0x01, ///< Enables exception handling support (say as optionally supported by C++) + Verbose = 0x02, ///< Give more verbose diagnostics + EnableSecurityChecks = 0x04, ///< Enable runtime security checks (such as for buffer + ///< overruns) - enabling typically decreases performance + EnableFloat16 = 0x08, ///< If set compiles with support for float16/half }; }; enum class OptimizationLevel : uint8_t { - None, ///< Don't optimize at all. - Default, ///< Default optimization level: balance code quality and compilation time. - High, ///< Optimize aggressively. - Maximal, ///< Include optimizations that may take a very long time, or may involve severe space-vs-speed tradeoffs + None, ///< Don't optimize at all. + Default, ///< Default optimization level: balance code quality and compilation time. + High, ///< Optimize aggressively. + Maximal, ///< Include optimizations that may take a very long time, or may involve severe + ///< space-vs-speed tradeoffs }; enum class DebugInfoType : uint8_t { - None, ///< Don't emit debug information at all. - Minimal, ///< Emit as little debug information as possible, while still supporting stack traces. - Standard, ///< Emit whatever is the standard level of debug information for each target. - Maximal, ///< Emit as much debug information as possible for each target. + None, ///< Don't emit debug information at all. + Minimal, ///< Emit as little debug information as possible, while still supporting stack + ///< traces. + Standard, ///< Emit whatever is the standard level of debug information for each target. + Maximal, ///< Emit as much debug information as possible for each target. }; enum class FloatingPointMode : uint8_t { @@ -192,7 +207,7 @@ struct DownstreamCompileOptions struct Define { - TerminatedCharSlice nameWithSig; ///< If macro takes parameters include in brackets + TerminatedCharSlice nameWithSig; ///< If macro takes parameters include in brackets TerminatedCharSlice value; }; @@ -200,7 +215,7 @@ struct DownstreamCompileOptions { enum class Kind : uint8_t { - CUDASM, ///< What the version is for + CUDASM, ///< What the version is for SPIRV, }; Kind kind; @@ -222,8 +237,9 @@ struct DownstreamCompileOptions PlatformKind platform = PlatformKind::Unknown; - /// The path/name of the output module. Should not have the extension, as that will be added for each of the target types. - /// If not set a module path will be internally generated internally on a command line based compiler + /// The path/name of the output module. Should not have the extension, as that will be added for + /// each of the target types. If not set a module path will be internally generated internally + /// on a command line based compiler TerminatedCharSlice modulePath; Slice defines; @@ -241,31 +257,32 @@ struct DownstreamCompileOptions /// For compilers/compiles that require an entry point name, else can be empty TerminatedCharSlice entryPointName; - /// Profile name to use, only required for compiles that need to compile against a a specific profiles. - /// Profile names are tied to compilers and targets. + /// Profile name to use, only required for compiles that need to compile against a a specific + /// profiles. Profile names are tied to compilers and targets. TerminatedCharSlice profileName; - /// The stage being compiled for + /// The stage being compiled for SlangStage stage = SLANG_STAGE_NONE; /// Arguments that are specific to a particular compiler implementation. Slice compilerSpecificArguments; - /// NOTE! Not all downstream compilers can use the fileSystemExt/sourceManager. This option will be ignored in those scenarios. + /// NOTE! Not all downstream compilers can use the fileSystemExt/sourceManager. This option will + /// be ignored in those scenarios. ISlangFileSystemExt* fileSystemExt = nullptr; SourceManager* sourceManager = nullptr; - // The debug info format to use. + // The debug info format to use. SlangDebugInfoFormat m_debugInfoFormat = SLANG_DEBUG_INFO_FORMAT_DEFAULT; }; static_assert(std::is_trivially_copyable_v); -#define SLANG_ALIAS_DEPRECATED_VERSION(name, id, firstField, lastField) \ -struct name##_AliasDeprecated##id \ -{ \ - static const ptrdiff_t kStart = SLANG_OFFSET_OF(name, firstField); \ - static const ptrdiff_t kEnd = SLANG_OFFSET_OF(name, lastField) + sizeof(name::lastField); \ -}; +#define SLANG_ALIAS_DEPRECATED_VERSION(name, id, firstField, lastField) \ + struct name##_AliasDeprecated##id \ + { \ + static const ptrdiff_t kStart = SLANG_OFFSET_OF(name, firstField); \ + static const ptrdiff_t kEnd = SLANG_OFFSET_OF(name, lastField) + sizeof(name::lastField); \ + }; /* Used to indicate what kind of products are expected to be produced for a compilation. */ typedef uint32_t DownstreamProductFlags; @@ -273,25 +290,29 @@ struct DownstreamProductFlag { enum Enum : DownstreamProductFlags { - Debug = 0x1, ///< Used by debugger during execution - Execution = 0x2, ///< Required for execution - Compile = 0x4, ///< A product *required* for compilation - Miscellaneous = 0x8, ///< Anything else + Debug = 0x1, ///< Used by debugger during execution + Execution = 0x2, ///< Required for execution + Compile = 0x4, ///< A product *required* for compilation + Miscellaneous = 0x8, ///< Anything else }; enum Mask : DownstreamProductFlags { - All = 0xf, ///< All the flags + All = 0xf, ///< All the flags }; }; class IDownstreamCompiler : public ICastable { public: - SLANG_COM_INTERFACE(0x167b8ba7, 0xbd41, 0x469a, { 0x92, 0x28, 0xb8, 0x53, 0xc8, 0xea, 0x56, 0x6d }) + SLANG_COM_INTERFACE( + 0x167b8ba7, + 0xbd41, + 0x469a, + {0x92, 0x28, 0xb8, 0x53, 0xc8, 0xea, 0x56, 0x6d}) typedef DownstreamCompilerDesc Desc; typedef DownstreamCompileOptions CompileOptions; - + typedef CompileOptions::OptimizationLevel OptimizationLevel; typedef CompileOptions::DebugInfoType DebugInfoType; typedef CompileOptions::FloatingPointMode FloatingPointMode; @@ -299,40 +320,63 @@ public: typedef CompileOptions::Define Define; typedef CompileOptions::CapabilityVersion CapabilityVersion; - /// Get the desc of this compiler + /// Get the desc of this compiler virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() = 0; - /// Compile using the specified options. The result is in resOut - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) = 0; - /// Returns true if compiler can do a transformation of `from` to `to` Artifact types - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert(const ArtifactDesc& from, const ArtifactDesc& to) = 0; - /// Converts an artifact `from` to a desc of `to` and puts the result in outArtifact - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) = 0; - /// Get the version of this compiler - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) = 0; - /// Validate and return the result - virtual SLANG_NO_THROW SlangResult SLANG_MCALL validate(const uint32_t* contents, int contentsSize) = 0; - - /// True if underlying compiler uses file system to communicate source + /// Compile using the specified options. The result is in resOut + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outArtifact) = 0; + /// Returns true if compiler can do a transformation of `from` to `to` Artifact types + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) = 0; + /// Converts an artifact `from` to a desc of `to` and puts the result in outArtifact + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) = 0; + /// Get the version of this compiler + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + getVersionString(slang::IBlob** outVersionString) = 0; + /// Validate and return the result + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + validate(const uint32_t* contents, int contentsSize) = 0; + + /// True if underlying compiler uses file system to communicate source virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() = 0; }; class DownstreamCompilerBase : public ComBaseObject, public IDownstreamCompiler { public: - SLANG_COM_BASE_IUNKNOWN_ALL + SLANG_COM_BASE_IUNKNOWN_ALL // ICastable virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; // IDownstreamCompiler virtual SLANG_NO_THROW const Desc& SLANG_MCALL getDesc() SLANG_OVERRIDE { return m_desc; } - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE { SLANG_UNUSED(from); SLANG_UNUSED(to); return false; } - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) SLANG_OVERRIDE { *outVersionString = nullptr; return SLANG_FAIL; } - virtual SLANG_NO_THROW SlangResult SLANG_MCALL validate(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE { SLANG_UNUSED(contents); SLANG_UNUSED(contentsSize); return SLANG_FAIL; } + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE + { + SLANG_UNUSED(from); + SLANG_UNUSED(to); + return false; + } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) + SLANG_OVERRIDE + { + *outVersionString = nullptr; + return SLANG_FAIL; + } + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + validate(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE + { + SLANG_UNUSED(contents); + SLANG_UNUSED(contentsSize); + return SLANG_FAIL; + } - DownstreamCompilerBase(const Desc& desc): - m_desc(desc) + DownstreamCompilerBase(const Desc& desc) + : m_desc(desc) { } DownstreamCompilerBase() {} @@ -349,36 +393,47 @@ public: typedef DownstreamCompilerBase Super; // IDownstreamCompiler - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return true; } // Functions to be implemented for a specific CommandLine - /// Given options determines the paths to products produced (including the 'moduleFilePath'). - /// Note that does *not* guarentee all products were or should be produced. Just aims to include all that could - /// be produced, such that can be removed on completion. - virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags flags, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts) = 0; + /// Given options determines the paths to products produced (including the 'moduleFilePath'). + /// Note that does *not* guarentee all products were or should be produced. Just aims to include + /// all that could be produced, such that can be removed on completion. + virtual SlangResult calcCompileProducts( + const CompileOptions& options, + DownstreamProductFlags flags, + IOSFileArtifactRepresentation* lockFile, + List>& outArtifacts) = 0; virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) = 0; - virtual SlangResult parseOutput(const ExecuteResult& exeResult, IArtifactDiagnostics* diagnostics) = 0; + virtual SlangResult parseOutput( + const ExecuteResult& exeResult, + IArtifactDiagnostics* diagnostics) = 0; - CommandLineDownstreamCompiler(const Desc& desc, const ExecutableLocation& exe) : - Super(desc) + CommandLineDownstreamCompiler(const Desc& desc, const ExecutableLocation& exe) + : Super(desc) { m_cmdLine.setExecutableLocation(exe); } - CommandLineDownstreamCompiler(const Desc& desc, const CommandLine& cmdLine) : - Super(desc), - m_cmdLine(cmdLine) - {} + CommandLineDownstreamCompiler(const Desc& desc, const CommandLine& cmdLine) + : Super(desc), m_cmdLine(cmdLine) + { + } - CommandLineDownstreamCompiler(const Desc& desc):Super(desc) {} + CommandLineDownstreamCompiler(const Desc& desc) + : Super(desc) + { + } CommandLine m_cmdLine; }; -/* Only purpose of having base-class here is to make all the DownstreamCompiler types available directly in derived Utils */ +/* Only purpose of having base-class here is to make all the DownstreamCompiler types available + * directly in derived Utils */ struct DownstreamCompilerUtilBase { typedef DownstreamCompileOptions CompileOptions; @@ -392,6 +447,6 @@ struct DownstreamCompilerUtilBase typedef DownstreamProductFlags ProductFlags; }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-dxc-compiler.cpp b/source/compiler-core/slang-dxc-compiler.cpp index 30bf71968..b694c4cf6 100644 --- a/source/compiler-core/slang-dxc-compiler.cpp +++ b/source/compiler-core/slang-dxc-compiler.cpp @@ -1,35 +1,28 @@ // slang-dxc-compiler.cpp #include "slang-dxc-compiler.h" -#include "../core/slang-common.h" -#include "slang-com-helper.h" - #include "../core/slang-blob.h" - -#include "../core/slang-string-util.h" -#include "../core/slang-string-slice-pool.h" - +#include "../core/slang-char-util.h" +#include "../core/slang-common.h" #include "../core/slang-io.h" -#include "../core/slang-shared-library.h" #include "../core/slang-semantic-version.h" -#include "../core/slang-char-util.h" - -#include "slang-include-system.h" -#include "slang-source-loc.h" - #include "../core/slang-shared-library.h" - +#include "../core/slang-string-slice-pool.h" +#include "../core/slang-string-util.h" #include "slang-artifact-associated-impl.h" -#include "slang-artifact-util.h" -#include "slang-artifact-diagnostic-util.h" #include "slang-artifact-desc-util.h" +#include "slang-artifact-diagnostic-util.h" +#include "slang-artifact-util.h" +#include "slang-com-helper.h" +#include "slang-include-system.h" +#include "slang-source-loc.h" // Enable DXIL by default unless told not to #ifndef SLANG_ENABLE_DXIL_SUPPORT #if SLANG_APPLE_FAMILY -# define SLANG_ENABLE_DXIL_SUPPORT 0 +#define SLANG_ENABLE_DXIL_SUPPORT 0 #else -# define SLANG_ENABLE_DXIL_SUPPORT 1 +#define SLANG_ENABLE_DXIL_SUPPORT 1 #endif #endif @@ -37,15 +30,15 @@ // generate code on Windows. #if SLANG_ENABLE_DXIL_SUPPORT -# ifdef _WIN32 -# include -# include -# endif +#ifdef _WIN32 +#include +#include +#endif -# include "../../external/dxc/dxcapi.h" +#include "../../external/dxc/dxcapi.h" -# ifndef _WIN32 -# ifdef __uuidof +#ifndef _WIN32 +#ifdef __uuidof // DXC's WinAdapter.h defines __uuidof(T) over types, but the existing // usage in this file is over values (both are accepted on MSVC.) // We also need to decay through Slang::ComPtr, hence the helper struct @@ -59,11 +52,10 @@ struct StripSlangComPtr> { using type = T; }; -# undef __uuidof -# define __uuidof(x) \ - __emulated_uuidof>::type>() -# endif -# endif +#undef __uuidof +#define __uuidof(x) __emulated_uuidof>::type>() +#endif +#endif #endif namespace Slang @@ -71,11 +63,15 @@ namespace Slang #if SLANG_ENABLE_DXIL_SUPPORT -static UnownedStringSlice _getSlice(IDxcBlob* blob) { return StringUtil::getSlice((ISlangBlob*)blob); } +static UnownedStringSlice _getSlice(IDxcBlob* blob) +{ + return StringUtil::getSlice((ISlangBlob*)blob); +} // IDxcIncludeHandler // 7f61fc7d-950d-467f-b3e3-3c02fb49187c -static const Guid IID_IDxcIncludeHandler = { 0x7f61fc7d, 0x950d, 0x467f, { 0x3c, 0x02, 0xfb, 0x49, 0x18, 0x7c } }; +static const Guid IID_IDxcIncludeHandler = + {0x7f61fc7d, 0x950d, 0x467f, {0x3c, 0x02, 0xfb, 0x49, 0x18, 0x7c}}; static UnownedStringSlice _addName(const UnownedStringSlice& inSlice, StringSlicePool& pool) { @@ -89,10 +85,10 @@ static UnownedStringSlice _addName(const UnownedStringSlice& inSlice, StringSlic const Index length = slice.getLength(); buf << slice; - for (Index i = 0; ; ++i) + for (Index i = 0;; ++i) { buf.reduceLength(length); - + if (i > 0) { buf << "_" << i; @@ -131,8 +127,8 @@ public: // Implement IDxcIncludeHandler virtual HRESULT SLANG_MCALL LoadSource(LPCWSTR inFilename, IDxcBlob** outSource) SLANG_OVERRIDE { - // Hmm DXC does something a bit odd - when it sees a path, it just passes that in with ./ in front!! - // NOTE! It doesn't make any difference if it is "" or <> quoted. + // Hmm DXC does something a bit odd - when it sees a path, it just passes that in with ./ in + // front!! NOTE! It doesn't make any difference if it is "" or <> quoted. // So we just do a work around where we strip if we see a path starting with ./ String filePath = String::fromWString(inFilename); @@ -141,9 +137,9 @@ public: if (filePath.startsWith("./")) { const String remaining = filePath.getUnownedSlice().tail(2); - - // Okay if we strip ./ and what we have is absolute, then it's the absolute path that we care about, - // otherwise we just leave as is. + + // Okay if we strip ./ and what we have is absolute, then it's the absolute path that we + // care about, otherwise we just leave as is. if (Path::isAbsolute(remaining)) { filePath = remaining; @@ -160,13 +156,15 @@ public: return res; } - DxcIncludeHandler(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager = nullptr) : - m_system(searchDirectories, fileSystemExt, sourceManager) + DxcIncludeHandler( + SearchDirectoryList* searchDirectories, + ISlangFileSystemExt* fileSystemExt, + SourceManager* sourceManager = nullptr) + : m_system(searchDirectories, fileSystemExt, sourceManager) { } protected: - // Used by QueryInterface for casting ISlangUnknown* getInterface(const Guid& guid) { @@ -176,7 +174,7 @@ protected: } return nullptr; } - + IncludeSystem m_system; }; @@ -186,11 +184,15 @@ public: typedef DownstreamCompilerBase Super; // IDownstreamCompiler - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; } - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) + SLANG_OVERRIDE; /// Must be called before use SlangResult init(ISlangSharedLibrary* library); @@ -198,13 +200,12 @@ public: DXCDownstreamCompiler() {} protected: - DxcCreateInstanceProc m_createInstance = nullptr; - /// The commit hash associated with the DXC dll used - /// If 0 length, no hash was found - String m_commitHash; - /// The commit count. 0 if not set + /// The commit hash associated with the DXC dll used + /// If 0 length, no hash was found + String m_commitHash; + /// The commit count. 0 if not set uint32_t m_commitCount = 0; ComPtr m_sharedLibrary; @@ -231,10 +232,13 @@ SlangResult DXCDownstreamCompiler::init(ISlangSharedLibrary* library) return SLANG_FAIL; } - // Must be able to create the compiler. We inly do this here, because we want to get the compiler - // version. + // Must be able to create the compiler. We inly do this here, because we want to get the + // compiler version. ComPtr dxcCompiler; - SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcCompiler, __uuidof(dxcCompiler), (LPVOID*)dxcCompiler.writeRef())); + SLANG_RETURN_ON_FAIL(m_createInstance( + CLSID_DxcCompiler, + __uuidof(dxcCompiler), + (LPVOID*)dxcCompiler.writeRef())); uint32_t major = 0; uint32_t minor = 0; @@ -277,12 +281,13 @@ SlangResult DXCDownstreamCompiler::init(ISlangSharedLibrary* library) StringBuilder buf; semanticVersion.append(buf); - if (customVersionString.startsWith(buf) && + if (customVersionString.startsWith(buf) && customVersionString.getLength() > buf.getLength() + 2 && customVersionString[buf.getLength()] == '.') { // Get the patch slice - UnownedStringSlice patchSlice = StringUtil::getAtInSplit(customVersionString.getUnownedSlice(), '.', 2); + UnownedStringSlice patchSlice = + StringUtil::getAtInSplit(customVersionString.getUnownedSlice(), '.', 2); Int patchValue; if (SLANG_SUCCEEDED(StringUtil::parseInt(patchSlice, patchValue)) && patchValue > 0) @@ -298,7 +303,11 @@ SlangResult DXCDownstreamCompiler::init(ISlangSharedLibrary* library) return SLANG_OK; } -static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const UnownedStringSlice& line, List& lineSlices, IArtifactDiagnostics::Diagnostic& outDiagnostic) +static SlangResult _parseDiagnosticLine( + SliceAllocator& allocator, + const UnownedStringSlice& line, + List& lineSlices, + IArtifactDiagnostics::Diagnostic& outDiagnostic) { /* tests/diagnostics/syntax-error-intrinsic.slang:14:2: error: expected expression */ if (lineSlices.getCount() < 5) @@ -310,8 +319,8 @@ static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const Unowned SLANG_RETURN_ON_FAIL(StringUtil::parseInt(lineSlices[1], outDiagnostic.location.line)); - //Int lineCol; - //SLANG_RETURN_ON_FAIL(StringUtil::parseInt(lineSlices[2], lineCol)); + // Int lineCol; + // SLANG_RETURN_ON_FAIL(StringUtil::parseInt(lineSlices[2], lineCol)); UnownedStringSlice severitySlice = lineSlices[3].trim(); @@ -326,7 +335,10 @@ static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const Unowned return SLANG_OK; } -static SlangResult _handleOperationResult(IDxcOperationResult* dxcResult, IArtifactDiagnostics* diagnostics, ComPtr& outBlob) +static SlangResult _handleOperationResult( + IDxcOperationResult* dxcResult, + IArtifactDiagnostics* diagnostics, + ComPtr& outBlob) { // Retrieve result. HRESULT resultCode = S_OK; @@ -355,7 +367,12 @@ static SlangResult _handleOperationResult(IDxcOperationResult* dxcResult, IArtif SliceAllocator allocator; List parsedDiagnostics; - SlangResult diagnosticParseRes = ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics(allocator, diagnosticsSlice, 0, _parseDiagnosticLine, diagnostics); + SlangResult diagnosticParseRes = ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics( + allocator, + diagnosticsSlice, + 0, + _parseDiagnosticLine, + diagnostics); SLANG_UNUSED(diagnosticParseRes); SLANG_ASSERT(SLANG_SUCCEEDED(diagnosticParseRes)); @@ -365,7 +382,8 @@ static SlangResult _handleOperationResult(IDxcOperationResult* dxcResult, IArtif // If it failed, make sure we have an error in the diagnostics if (SLANG_FAILED(resultCode)) { - // In case the parsing failed, we still have an error -> so require there is one in the diagnostics + // In case the parsing failed, we still have an error -> so require there is one in the + // diagnostics diagnostics->requireErrorDiagnostic(); } else @@ -380,7 +398,7 @@ static SlangResult _handleOperationResult(IDxcOperationResult* dxcResult, IArtif SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArtifact** outArtifact) { - if (!isVersionCompatible(inOptions)) + if (!isVersionCompatible(inOptions)) { // Not possible to compile with this version of the interface. return SLANG_E_NOT_IMPLEMENTED; @@ -389,7 +407,8 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt CompileOptions options = getCompatibleVersion(&inOptions); // This compiler can only deal at most, a single source code artifact - // Should be okay to link together multiple libraries without any source artifacts (assuming that means source code) + // Should be okay to link together multiple libraries without any source artifacts (assuming + // that means source code) if (options.sourceArtifacts.count > 1) { return SLANG_FAIL; @@ -401,7 +420,8 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt if (hasSource) { - if (options.sourceLanguage != SLANG_SOURCE_LANGUAGE_HLSL || options.targetType != SLANG_DXIL) + if (options.sourceLanguage != SLANG_SOURCE_LANGUAGE_HLSL || + options.targetType != SLANG_DXIL) { SLANG_ASSERT(!"Can only compile HLSL to DXIL"); return SLANG_FAIL; @@ -425,9 +445,13 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt } ComPtr dxcCompiler; - SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcCompiler, __uuidof(dxcCompiler), (LPVOID*)dxcCompiler.writeRef())); + SLANG_RETURN_ON_FAIL(m_createInstance( + CLSID_DxcCompiler, + __uuidof(dxcCompiler), + (LPVOID*)dxcCompiler.writeRef())); ComPtr dxcLibrary; - SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcLibrary, __uuidof(dxcLibrary), (LPVOID*)dxcLibrary.writeRef())); + SLANG_RETURN_ON_FAIL( + m_createInstance(CLSID_DxcLibrary, __uuidof(dxcLibrary), (LPVOID*)dxcLibrary.writeRef())); ComPtr dxcSourceBlob = nullptr; ComPtr sourceBlob; @@ -464,45 +488,36 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt switch (options.matrixLayout) { - default: - break; + default: break; - case SLANG_MATRIX_LAYOUT_ROW_MAJOR: - args.add(L"-Zpr"); - break; + case SLANG_MATRIX_LAYOUT_ROW_MAJOR: args.add(L"-Zpr"); break; } switch (options.floatingPointMode) { - default: - break; + default: break; - case FloatingPointMode::Precise: - args.add(L"-Gis"); // "force IEEE strictness" - break; + case FloatingPointMode::Precise: + args.add(L"-Gis"); // "force IEEE strictness" + break; } - switch (options.optimizationLevel) { - default: - break; + default: break; - case OptimizationLevel::None: args.add(L"-Od"); break; - case OptimizationLevel::Default: args.add(L"-O1"); break; - case OptimizationLevel::High: args.add(L"-O2"); break; - case OptimizationLevel::Maximal: args.add(L"-O3"); break; + case OptimizationLevel::None: args.add(L"-Od"); break; + case OptimizationLevel::Default: args.add(L"-O1"); break; + case OptimizationLevel::High: args.add(L"-O2"); break; + case OptimizationLevel::Maximal: args.add(L"-O3"); break; } switch (options.debugInfoType) { - case DebugInfoType::None: - break; + case DebugInfoType::None: break; - default: - args.add(L"-Zi"); - break; + default: args.add(L"-Zi"); break; } // Slang strives to produce correct code, and by default @@ -556,9 +571,9 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt searchDirectories.searchDirectories.add(asString(includePath)); } - // TODO(JS): - // We don't want to enable HLSL2021 on DXC by default even if it's available because it has - // changes that break things. Such as with operator ?:. So for now we disable. +// TODO(JS): +// We don't want to enable HLSL2021 on DXC by default even if it's available because it has +// changes that break things. Such as with operator ?:. So for now we disable. #if 0 // TODO(JS): Enable in a better way perhaps? { @@ -586,27 +601,33 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt sourcePath = ArtifactUtil::findPath(sourceArtifact); OSString wideSourcePath = sourcePath.toWString(); - DxcIncludeHandler includeHandler(&searchDirectories, options.fileSystemExt, options.sourceManager); + DxcIncludeHandler includeHandler( + &searchDirectories, + options.fileSystemExt, + options.sourceManager); - SLANG_RETURN_ON_FAIL(dxcCompiler->Compile(dxcSourceBlob, + SLANG_RETURN_ON_FAIL(dxcCompiler->Compile( + dxcSourceBlob, wideSourcePath.begin(), wideEntryPointName.begin(), wideProfileName.begin(), args.getBuffer(), UINT32(args.getCount()), - nullptr, // `#define`s - 0, // `#define` count - &includeHandler, // `#include` handler + nullptr, // `#define`s + 0, // `#define` count + &includeHandler, // `#include` handler dxcOperationResult.writeRef())); - SLANG_RETURN_ON_FAIL(_handleOperationResult(dxcOperationResult, diagnostics, dxcResultBlob)); + SLANG_RETURN_ON_FAIL( + _handleOperationResult(dxcOperationResult, diagnostics, dxcResultBlob)); } // If we have libraries then we need to link... if (libraries.getCount()) { ComPtr linker; - SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcLinker, __uuidof(linker), (void**)linker.writeRef())); + SLANG_RETURN_ON_FAIL( + m_createInstance(CLSID_DxcLinker, __uuidof(linker), (void**)linker.writeRef())); StringSlicePool pool(StringSlicePool::Style::Default); @@ -648,22 +669,30 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt SLANG_ASSERT(libraryNames.getCount() == librariesCount); List linkLibraryNames; - + linkLibraryNames.setCount(librariesCount); - + for (Index i = 0; i < librariesCount; ++i) { linkLibraryNames[i] = libraryNames[i].begin(); // Register the library - SLANG_RETURN_ON_FAIL(linker->RegisterLibrary(linkLibraryNames[i], (IDxcBlob*)libraryBlobs[i].get())); + SLANG_RETURN_ON_FAIL( + linker->RegisterLibrary(linkLibraryNames[i], (IDxcBlob*)libraryBlobs[i].get())); } // Use the original profile name wideProfileName = asString(options.profileName).toWString(); ComPtr linkDxcResult; - SLANG_RETURN_ON_FAIL(linker->Link(wideEntryPointName.begin(), wideProfileName.begin(), linkLibraryNames.getBuffer(), UINT32(librariesCount), nullptr, 0, linkDxcResult.writeRef())); + SLANG_RETURN_ON_FAIL(linker->Link( + wideEntryPointName.begin(), + wideProfileName.begin(), + linkLibraryNames.getBuffer(), + UINT32(librariesCount), + nullptr, + 0, + linkDxcResult.writeRef())); ComPtr linkedBlob; SLANG_RETURN_ON_FAIL(_handleOperationResult(linkDxcResult, diagnostics, linkedBlob)); @@ -696,9 +725,15 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt ComPtr pdbBlob; ComPtr nameBlob; - if (SLANG_SUCCEEDED(dxcResult->GetOutput(DXC_OUT_PDB, __uuidof(pdbBlob), (void**)pdbBlob.writeRef(), nameBlob.writeRef()))) + if (SLANG_SUCCEEDED(dxcResult->GetOutput( + DXC_OUT_PDB, + __uuidof(pdbBlob), + (void**)pdbBlob.writeRef(), + nameBlob.writeRef()))) { - auto pdbArtifact = ArtifactUtil::createArtifact(ArtifactDesc::make(ArtifactDesc::Kind::BinaryFormat, ArtifactDesc::Payload::PdbDebugInfo)); + auto pdbArtifact = ArtifactUtil::createArtifact(ArtifactDesc::make( + ArtifactDesc::Kind::BinaryFormat, + ArtifactDesc::Payload::PdbDebugInfo)); if (nameBlob) { @@ -707,7 +742,8 @@ SlangResult DXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt const auto name = String::fromWString(wideName); if (name.getLength()) { - // Set the name on the artifact. This is the name that must be used for the PDB to be loadable as a file by other tooling. + // Set the name on the artifact. This is the name that must be used for + // the PDB to be loadable as a file by other tooling. pdbArtifact->setName(name.getBuffer()); } } @@ -730,7 +766,10 @@ bool DXCDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactD return ArtifactDescUtil::isDisassembly(from, to) && from.payload == ArtifactPayload::DXIL; } -SlangResult DXCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) +SlangResult DXCDownstreamCompiler::convert( + IArtifact* from, + const ArtifactDesc& to, + IArtifact** outArtifact) { // Can only disassemble blobs that are DXIL if (!canConvert(from->getDesc(), to)) @@ -742,13 +781,21 @@ SlangResult DXCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& SLANG_RETURN_ON_FAIL(from->loadBlob(ArtifactKeep::No, dxilBlob.writeRef())); ComPtr dxcCompiler; - SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcCompiler, __uuidof(dxcCompiler), (LPVOID*)dxcCompiler.writeRef())); + SLANG_RETURN_ON_FAIL(m_createInstance( + CLSID_DxcCompiler, + __uuidof(dxcCompiler), + (LPVOID*)dxcCompiler.writeRef())); ComPtr dxcLibrary; - SLANG_RETURN_ON_FAIL(m_createInstance(CLSID_DxcLibrary, __uuidof(dxcLibrary), (LPVOID*)dxcLibrary.writeRef())); + SLANG_RETURN_ON_FAIL( + m_createInstance(CLSID_DxcLibrary, __uuidof(dxcLibrary), (LPVOID*)dxcLibrary.writeRef())); // Create blob from the input data ComPtr dxcSourceBlob; - SLANG_RETURN_ON_FAIL(dxcLibrary->CreateBlobWithEncodingFromPinned((LPBYTE)dxilBlob->getBufferPointer(), (UINT32)dxilBlob->getBufferSize(), 0, dxcSourceBlob.writeRef())); + SLANG_RETURN_ON_FAIL(dxcLibrary->CreateBlobWithEncodingFromPinned( + (LPBYTE)dxilBlob->getBufferPointer(), + (UINT32)dxilBlob->getBufferSize(), + 0, + dxcSourceBlob.writeRef())); ComPtr dxcResultBlob; SLANG_RETURN_ON_FAIL(dxcCompiler->Disassemble(dxcSourceBlob, dxcResultBlob.writeRef())); @@ -770,26 +817,36 @@ SlangResult DXCDownstreamCompiler::getVersionString(slang::IBlob** outVersionStr m_desc.version.append(versionString); if (m_commitHash.getLength()) - { + { versionString << "#" << m_commitHash; } else { // If we don't have the commitHash, we use the library timestamp, to uniquely identify. - versionString << " " << SharedLibraryUtils::getSharedLibraryTimestamp(reinterpret_cast(m_createInstance)); + versionString << " " + << SharedLibraryUtils::getSharedLibraryTimestamp( + reinterpret_cast(m_createInstance)); } *outVersionString = StringBlob::moveCreate(versionString).detach(); return SLANG_OK; } -/* static */SlangResult DXCDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult DXCDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { ComPtr library; - const char* dependentNames[] = {"dxil", nullptr } ; - SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary(path, loader, dependentNames, "dxcompiler", library)); - + const char* dependentNames[] = {"dxil", nullptr}; + SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary( + path, + loader, + dependentNames, + "dxcompiler", + library)); + SLANG_ASSERT(library); if (!library) { @@ -806,7 +863,10 @@ SlangResult DXCDownstreamCompiler::getVersionString(slang::IBlob** outVersionStr #else // SLANG_ENABLE_DXIL_SUPPORT -/* static */SlangResult DXCDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult DXCDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { SLANG_UNUSED(path); SLANG_UNUSED(loader); @@ -816,4 +876,4 @@ SlangResult DXCDownstreamCompiler::getVersionString(slang::IBlob** outVersionStr #endif // SLANG_ENABLE_DXIL_SUPPORT -} +} // namespace Slang diff --git a/source/compiler-core/slang-dxc-compiler.h b/source/compiler-core/slang-dxc-compiler.h index 4c915fb19..ee1d93c48 100644 --- a/source/compiler-core/slang-dxc-compiler.h +++ b/source/compiler-core/slang-dxc-compiler.h @@ -1,18 +1,20 @@ #ifndef SLANG_DXC_COMPILER_UTIL_H #define SLANG_DXC_COMPILER_UTIL_H -#include "slang-downstream-compiler-util.h" - #include "../core/slang-platform.h" +#include "slang-downstream-compiler-util.h" namespace Slang { struct DXCDownstreamCompilerUtil { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-fxc-compiler.cpp b/source/compiler-core/slang-fxc-compiler.cpp index e4a9f25c7..0c571c10b 100644 --- a/source/compiler-core/slang-fxc-compiler.cpp +++ b/source/compiler-core/slang-fxc-compiler.cpp @@ -3,43 +3,36 @@ #if SLANG_ENABLE_DXBC_SUPPORT -#include "../core/slang-common.h" -#include "slang-com-helper.h" - #include "../core/slang-blob.h" - -#include "../core/slang-string-util.h" -#include "../core/slang-string-slice-pool.h" - +#include "../core/slang-char-util.h" +#include "../core/slang-common.h" #include "../core/slang-io.h" -#include "../core/slang-shared-library.h" #include "../core/slang-semantic-version.h" -#include "../core/slang-char-util.h" - -#include "slang-include-system.h" -#include "slang-source-loc.h" - +#include "../core/slang-shared-library.h" +#include "../core/slang-string-slice-pool.h" +#include "../core/slang-string-util.h" #include "slang-artifact-associated-impl.h" #include "slang-artifact-desc-util.h" #include "slang-artifact-diagnostic-util.h" - -#include "../core/slang-shared-library.h" +#include "slang-com-helper.h" +#include "slang-include-system.h" +#include "slang-source-loc.h" // Enable calling through to `fxc` or `dxc` to // generate code on Windows. #ifdef _WIN32 -# include -# include +#include +#include #endif // Some of the `D3DCOMPILE_*` constants aren't available in all // versions of `d3dcompiler.h`, so we define them here just in case #ifndef D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES -# define D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES (1 << 20) +#define D3DCOMPILE_ENABLE_UNBOUNDED_DESCRIPTOR_TABLES (1 << 20) #endif #ifndef D3DCOMPILE_ALL_RESOURCES_BOUND -# define D3DCOMPILE_ALL_RESOURCES_BOUND (1 << 21) +#define D3DCOMPILE_ALL_RESOURCES_BOUND (1 << 21) #endif #endif // SLANG_ENABLE_DXBC_SUPPORT @@ -49,25 +42,35 @@ namespace Slang #if SLANG_ENABLE_DXBC_SUPPORT -static UnownedStringSlice _getSlice(ID3DBlob* blob) { return StringUtil::getSlice((ISlangBlob*)blob); } +static UnownedStringSlice _getSlice(ID3DBlob* blob) +{ + return StringUtil::getSlice((ISlangBlob*)blob); +} struct FxcIncludeHandler : ID3DInclude { - STDMETHOD(Open)(D3D_INCLUDE_TYPE includeType, LPCSTR fileName, LPCVOID parentData, LPCVOID* outData, UINT* outSize) override + STDMETHOD(Open) + (D3D_INCLUDE_TYPE includeType, + LPCSTR fileName, + LPCVOID parentData, + LPCVOID* outData, + UINT* outSize) override { SLANG_UNUSED(includeType); // NOTE! The pParentData means the *text* of any previous include. - // In order to work out what *path* that came from, we need to seach which source file it came from, and - // use it's path + // In order to work out what *path* that came from, we need to seach which source file it + // came from, and use it's path - // Assume the root pathInfo initially + // Assume the root pathInfo initially PathInfo includedFromPathInfo = m_rootPathInfo; // Lets try and find the parent source if there is any if (parentData) { - SourceFile* foundSourceFile = m_system.getSourceManager()->findSourceFileByContentRecursively((const char*)parentData); + SourceFile* foundSourceFile = + m_system.getSourceManager()->findSourceFileByContentRecursively( + (const char*)parentData); if (foundSourceFile) { includedFromPathInfo = foundSourceFile->getPathInfo(); @@ -78,7 +81,8 @@ struct FxcIncludeHandler : ID3DInclude PathInfo pathInfo; ComPtr blob; - SLANG_RETURN_ON_FAIL(m_system.findAndLoadFile(path, includedFromPathInfo.foundPath, pathInfo, blob)); + SLANG_RETURN_ON_FAIL( + m_system.findAndLoadFile(path, includedFromPathInfo.foundPath, pathInfo, blob)); // Return the data *outData = blob->getBufferPointer(); @@ -92,8 +96,11 @@ struct FxcIncludeHandler : ID3DInclude SLANG_UNUSED(pData); return S_OK; } - FxcIncludeHandler(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager) : - m_system(searchDirectories, fileSystemExt, sourceManager) + FxcIncludeHandler( + SearchDirectoryList* searchDirectories, + ISlangFileSystemExt* fileSystemExt, + SourceManager* sourceManager) + : m_system(searchDirectories, fileSystemExt, sourceManager) { } @@ -107,22 +114,24 @@ public: typedef DownstreamCompilerBase Super; // IDownstreamCompiler - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; } - /// Must be called before use + /// Must be called before use SlangResult init(ISlangSharedLibrary* library); FXCDownstreamCompiler() {} - -protected: +protected: pD3DCompile m_compile = nullptr; pD3DDisassemble m_disassemble = nullptr; - ComPtr m_sharedLibrary; + ComPtr m_sharedLibrary; }; SlangResult FXCDownstreamCompiler::init(ISlangSharedLibrary* library) @@ -143,21 +152,29 @@ SlangResult FXCDownstreamCompiler::init(ISlangSharedLibrary* library) return SLANG_OK; } -static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const UnownedStringSlice& line, List& lineSlices, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseDiagnosticLine( + SliceAllocator& allocator, + const UnownedStringSlice& line, + List& lineSlices, + ArtifactDiagnostic& outDiagnostic) { - /* tests/diagnostics/syntax-error-intrinsic.slang(14,2): error X3000: syntax error: unexpected token '@' */ + /* tests/diagnostics/syntax-error-intrinsic.slang(14,2): error X3000: syntax error: unexpected + * token '@' */ if (lineSlices.getCount() < 3) { return SLANG_FAIL; } - SLANG_RETURN_ON_FAIL(ArtifactDiagnosticUtil::splitPathLocation(allocator, lineSlices[0], outDiagnostic)); + SLANG_RETURN_ON_FAIL( + ArtifactDiagnosticUtil::splitPathLocation(allocator, lineSlices[0], outDiagnostic)); { const UnownedStringSlice severityAndCodeSlice = lineSlices[1].trim(); - const UnownedStringSlice severitySlice = StringUtil::getAtInSplit(severityAndCodeSlice, ' ', 0); + const UnownedStringSlice severitySlice = + StringUtil::getAtInSplit(severityAndCodeSlice, ' ', 0); - outDiagnostic.code = allocator.allocate(StringUtil::getAtInSplit(severityAndCodeSlice, ' ', 1)); + outDiagnostic.code = + allocator.allocate(StringUtil::getAtInSplit(severityAndCodeSlice, ' ', 1)); outDiagnostic.severity = ArtifactDiagnostic::Severity::Error; if (severitySlice == "warning") @@ -212,10 +229,13 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt // Use the default fileSystemExt is not set ID3DInclude* includeHandler = nullptr; - FxcIncludeHandler fxcIncludeHandlerStorage(&searchDirectories, options.fileSystemExt, options.sourceManager); + FxcIncludeHandler fxcIncludeHandlerStorage( + &searchDirectories, + options.fileSystemExt, + options.sourceManager); if (options.fileSystemExt) { - + if (sourcePath.getLength() > 0) { fxcIncludeHandlerStorage.m_rootPathInfo = PathInfo::makePath(sourcePath); @@ -235,7 +255,7 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt dxMacro.Definition = define.value; dxMacrosStorage.add(dxMacro); } - D3D_SHADER_MACRO nullTerminator = { 0, 0 }; + D3D_SHADER_MACRO nullTerminator = {0, 0}; dxMacrosStorage.add(nullTerminator); dxMacros = dxMacrosStorage.getBuffer(); @@ -245,12 +265,9 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt switch (options.floatingPointMode) { - default: - break; + default: break; - case FloatingPointMode::Precise: - flags |= D3DCOMPILE_IEEE_STRICTNESS; - break; + case FloatingPointMode::Precise: flags |= D3DCOMPILE_IEEE_STRICTNESS; break; } flags |= D3DCOMPILE_ENABLE_STRICTNESS; @@ -258,23 +275,19 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt switch (options.optimizationLevel) { - default: - break; + default: break; - case OptimizationLevel::None: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0; break; - case OptimizationLevel::Default: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL1; break; - case OptimizationLevel::High: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL2; break; - case OptimizationLevel::Maximal: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3; break; + case OptimizationLevel::None: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL0; break; + case OptimizationLevel::Default: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL1; break; + case OptimizationLevel::High: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL2; break; + case OptimizationLevel::Maximal: flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3; break; } switch (options.debugInfoType) { - case DebugInfoType::None: - break; + case DebugInfoType::None: break; - default: - flags |= D3DCOMPILE_DEBUG; - break; + default: flags |= D3DCOMPILE_DEBUG; break; } ComPtr sourceBlob; @@ -307,7 +320,12 @@ SlangResult FXCDownstreamCompiler::compile(const CompileOptions& inOptions, IArt UnownedStringSlice diagnosticText = _getSlice(diagnosticsBlob); diagnostics->setRaw(asCharSlice(diagnosticText)); - SlangResult diagnosticParseRes = ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics(allocator, diagnosticText, 0, _parseDiagnosticLine, diagnostics); + SlangResult diagnosticParseRes = ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics( + allocator, + diagnosticText, + 0, + _parseDiagnosticLine, + diagnostics); SLANG_UNUSED(diagnosticParseRes); SLANG_ASSERT(SLANG_SUCCEEDED(diagnosticParseRes)); } @@ -338,7 +356,10 @@ bool FXCDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactD return ArtifactDescUtil::isDisassembly(from, to) && from.payload == ArtifactPayload::DXBC; } -SlangResult FXCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) +SlangResult FXCDownstreamCompiler::convert( + IArtifact* from, + const ArtifactDesc& to, + IArtifact** outArtifact) { if (!canConvert(from->getDesc(), to)) { @@ -349,22 +370,31 @@ SlangResult FXCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& SLANG_RETURN_ON_FAIL(from->loadBlob(ArtifactKeep::No, dxbcBlob.writeRef())); ComPtr disassemblyBlob; - SLANG_RETURN_ON_FAIL(m_disassemble(dxbcBlob->getBufferPointer(), dxbcBlob->getBufferSize(), 0, nullptr, disassemblyBlob.writeRef())); + SLANG_RETURN_ON_FAIL(m_disassemble( + dxbcBlob->getBufferPointer(), + dxbcBlob->getBufferSize(), + 0, + nullptr, + disassemblyBlob.writeRef())); auto artifact = ArtifactUtil::createArtifact(to); // ISlangBlob is compatible with ID3DBlob artifact->addRepresentationUnknown((ISlangBlob*)disassemblyBlob.get()); - *outArtifact= artifact.detach(); + *outArtifact = artifact.detach(); return SLANG_OK; } -/* static */SlangResult FXCDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult FXCDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { ComPtr library; const char* const libName = "d3dcompiler_47"; - SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, libName, library)); + SLANG_RETURN_ON_FAIL( + DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, libName, library)); SLANG_ASSERT(library); if (!library) @@ -383,7 +413,10 @@ SlangResult FXCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& #else // SLANG_ENABLE_DXBC_SUPPORT -/* static */SlangResult FXCDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult FXCDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { SLANG_UNUSED(path); SLANG_UNUSED(loader); @@ -393,4 +426,4 @@ SlangResult FXCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& #endif // else SLANG_ENABLE_DXBC_SUPPORT -} +} // namespace Slang diff --git a/source/compiler-core/slang-fxc-compiler.h b/source/compiler-core/slang-fxc-compiler.h index 856d2fc0e..9ab072de0 100644 --- a/source/compiler-core/slang-fxc-compiler.h +++ b/source/compiler-core/slang-fxc-compiler.h @@ -1,18 +1,20 @@ #ifndef SLANG_FXC_COMPILER_UTIL_H #define SLANG_FXC_COMPILER_UTIL_H -#include "slang-downstream-compiler-util.h" - #include "../core/slang-platform.h" +#include "slang-downstream-compiler-util.h" namespace Slang { struct FXCDownstreamCompilerUtil { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-gcc-compiler-util.cpp b/source/compiler-core/slang-gcc-compiler-util.cpp index 875f7bea1..67ee6f8b3 100644 --- a/source/compiler-core/slang-gcc-compiler-util.cpp +++ b/source/compiler-core/slang-gcc-compiler-util.cpp @@ -1,19 +1,17 @@ // slang-gcc-compiler-util.cpp #include "slang-gcc-compiler-util.h" +#include "../core/slang-char-util.h" #include "../core/slang-common.h" -#include "slang-com-helper.h" -#include "../core/slang-string-util.h" - #include "../core/slang-io.h" #include "../core/slang-shared-library.h" -#include "../core/slang-char-util.h" #include "../core/slang-string-slice-pool.h" - +#include "../core/slang-string-util.h" #include "slang-artifact-desc-util.h" #include "slang-artifact-diagnostic-util.h" -#include "slang-artifact-util.h" #include "slang-artifact-representation-impl.h" +#include "slang-artifact-util.h" +#include "slang-com-helper.h" namespace Slang { @@ -44,7 +42,10 @@ static Index _findVersionEnd(const UnownedStringSlice& in) return len; } -/* static */SlangResult GCCDownstreamCompilerUtil::parseVersion(const UnownedStringSlice& text, const UnownedStringSlice& prefix, DownstreamCompilerDesc& outDesc) +/* static */ SlangResult GCCDownstreamCompilerUtil::parseVersion( + const UnownedStringSlice& text, + const UnownedStringSlice& prefix, + DownstreamCompilerDesc& outDesc) { List lines; StringUtil::calcLines(text, lines); @@ -57,7 +58,8 @@ static Index _findVersionEnd(const UnownedStringSlice& in) continue; } - const UnownedStringSlice remainingSlice = UnownedStringSlice(line.begin() + prefixIndex + prefix.getLength(), line.end()).trim(); + const UnownedStringSlice remainingSlice = + UnownedStringSlice(line.begin() + prefixIndex + prefix.getLength(), line.end()).trim(); const Index versionEndIndex = _findVersionEnd(remainingSlice); if (versionEndIndex < 0) @@ -65,9 +67,11 @@ static Index _findVersionEnd(const UnownedStringSlice& in) return SLANG_FAIL; } - const UnownedStringSlice versionSlice(remainingSlice.begin(), remainingSlice.begin() + versionEndIndex); + const UnownedStringSlice versionSlice( + remainingSlice.begin(), + remainingSlice.begin() + versionEndIndex); - // Version is in format 0.0.0 + // Version is in format 0.0.0 List split; StringUtil::split(versionSlice, '.', split); List digits; @@ -91,7 +95,9 @@ static Index _findVersionEnd(const UnownedStringSlice& in) return SLANG_FAIL; } -SlangResult GCCDownstreamCompilerUtil::calcVersion(const ExecutableLocation& exe, DownstreamCompilerDesc& outDesc) +SlangResult GCCDownstreamCompilerUtil::calcVersion( + const ExecutableLocation& exe, + DownstreamCompilerDesc& outDesc) { CommandLine cmdLine; cmdLine.setExecutableLocation(exe); @@ -102,16 +108,14 @@ SlangResult GCCDownstreamCompilerUtil::calcVersion(const ExecutableLocation& exe // Note we now have builds that add other words in front of the version // such as "Ubuntu clang version" - const UnownedStringSlice prefixes[] = - { + const UnownedStringSlice prefixes[] = { UnownedStringSlice::fromLiteral("clang version"), UnownedStringSlice::fromLiteral("gcc version"), UnownedStringSlice::fromLiteral("Apple LLVM version"), UnownedStringSlice::fromLiteral("Apple metal version"), }; - const SlangPassThrough types[] = - { + const SlangPassThrough types[] = { SLANG_PASS_THROUGH_CLANG, SLANG_PASS_THROUGH_GCC, SLANG_PASS_THROUGH_CLANG, @@ -125,7 +129,8 @@ SlangResult GCCDownstreamCompilerUtil::calcVersion(const ExecutableLocation& exe // Set the type outDesc.type = types[i]; // Extract the version - if (SLANG_SUCCEEDED(parseVersion(exeRes.standardError.getUnownedSlice(), prefixes[i], outDesc))) + if (SLANG_SUCCEEDED( + parseVersion(exeRes.standardError.getUnownedSlice(), prefixes[i], outDesc))) { return SLANG_OK; } @@ -134,7 +139,9 @@ SlangResult GCCDownstreamCompilerUtil::calcVersion(const ExecutableLocation& exe return SLANG_FAIL; } -static SlangResult _parseSeverity(const UnownedStringSlice& in, ArtifactDiagnostic::Severity& outSeverity) +static SlangResult _parseSeverity( + const UnownedStringSlice& in, + ArtifactDiagnostic::Severity& outSeverity) { typedef ArtifactDiagnostic::Severity Severity; @@ -157,28 +164,33 @@ static SlangResult _parseSeverity(const UnownedStringSlice& in, ArtifactDiagnost return SLANG_OK; } -namespace { // anonymous +namespace +{ // anonymous enum class LineParseResult { - Single, ///< It's a single line - Start, ///< Line was the start of a message - Continuation, ///< Not totally clear, add to previous line if nothing else hit - Ignore, ///< Ignore the line + Single, ///< It's a single line + Start, ///< Line was the start of a message + Continuation, ///< Not totally clear, add to previous line if nothing else hit + Ignore, ///< Ignore the line }; - -} // anonymous - -static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedStringSlice& line, LineParseResult& outLineParseResult, ArtifactDiagnostic& outDiagnostic) + +} // namespace + +static SlangResult _parseGCCFamilyLine( + SliceAllocator& allocator, + const UnownedStringSlice& line, + LineParseResult& outLineParseResult, + ArtifactDiagnostic& outDiagnostic) { typedef ArtifactDiagnostic Diagnostic; typedef Diagnostic::Severity Severity; - + // Set to default case outLineParseResult = LineParseResult::Ignore; /* example error output from different scenarios */ - + /* tests/cpp-compiler/c-compile-error.c: In function 'int main(int, char**)': tests/cpp-compiler/c-compile-error.c:8:13: error: 'b' was not declared in this scope @@ -189,25 +201,26 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS ^ */ - /* /tmp/ccS0JCWe.o:c-compile-link-error.c:(.rdata$.refptr.thing[.refptr.thing]+0x0): undefined reference to `thing' - collect2: error: ld returned 1 exit status*/ + /* /tmp/ccS0JCWe.o:c-compile-link-error.c:(.rdata$.refptr.thing[.refptr.thing]+0x0): undefined + reference to `thing' collect2: error: ld returned 1 exit status*/ /* - clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated] - Undefined symbols for architecture x86_64: + clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated + [-Wdeprecated] Undefined symbols for architecture x86_64: "_thing", referenced from: _main in c-compile-link-error-a83ace.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) */ - /* /tmp/c-compile-link-error-ccf151.o: In function `main': - c-compile-link-error.c:(.text+0x19): undefined reference to `thing' - clang: error: linker command failed with exit code 1 (use -v to see invocation) - */ + /* /tmp/c-compile-link-error-ccf151.o: In function `main': + c-compile-link-error.c:(.text+0x19): undefined reference to `thing' + clang: error: linker command failed with exit code 1 (use -v to see invocation) + */ - /* /tmp/c-compile-link-error-301c8c.o: In function `main': - /home/travis/build/shader-slang/slang/tests/cpp-compiler/c-compile-link-error.c:10: undefined reference to `thing' - clang-7: error: linker command failed with exit code 1 (use -v to see invocation)*/ + /* /tmp/c-compile-link-error-301c8c.o: In function `main': + /home/travis/build/shader-slang/slang/tests/cpp-compiler/c-compile-link-error.c:10: undefined + reference to `thing' clang-7: error: linker command failed with exit code 1 (use -v to see + invocation)*/ /* /path/slang-cpp-prelude.h:4:10: fatal error: ../slang.h: No such file or directory #include "slang.h" @@ -221,7 +234,8 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS List split; StringUtil::split(line, ':', split); - // On windows we can have paths that are a: etc... if we detect this we can combine 0 - 1 to be 1. + // On windows we can have paths that are a: etc... if we detect this we can combine 0 - 1 to + // be 1. if (split.getCount() > 1 && split[0].getLength() == 1) { const char c = split[0][0]; @@ -328,7 +342,7 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS outDiagnostic.severity = Diagnostic::Severity::Error; outDiagnostic.stage = Diagnostic::Stage::Link; outDiagnostic.text = allocator.allocate(split[3]); - + outLineParseResult = LineParseResult::Start; return SLANG_OK; } @@ -353,55 +367,60 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -/* static */SlangResult GCCDownstreamCompilerUtil::parseOutput(const ExecuteResult& exeRes, IArtifactDiagnostics* diagnostics) +/* static */ SlangResult GCCDownstreamCompilerUtil::parseOutput( + const ExecuteResult& exeRes, + IArtifactDiagnostics* diagnostics) { LineParseResult prevLineResult = LineParseResult::Ignore; - + SliceAllocator allocator; diagnostics->reset(); diagnostics->setRaw(SliceUtil::asCharSlice(exeRes.standardError)); - // We hold in workDiagnostics so as it is more convenient to append to the last with a continuation - // also means we don't hold the allocations of building up continuations, just the results when finally allocated at the end + // We hold in workDiagnostics so as it is more convenient to append to the last with a + // continuation also means we don't hold the allocations of building up continuations, just the + // results when finally allocated at the end List workDiagnostics; for (auto line : LineParser(exeRes.standardError.getUnownedSlice())) { ArtifactDiagnostic diagnostic; - + LineParseResult lineRes; - + SLANG_RETURN_ON_FAIL(_parseGCCFamilyLine(allocator, line, lineRes, diagnostic)); - + switch (lineRes) { - case LineParseResult::Start: + case LineParseResult::Start: { // It's start of a new message workDiagnostics.add(diagnostic); prevLineResult = LineParseResult::Start; break; } - case LineParseResult::Single: + case LineParseResult::Single: { // It's a single message, without anything following workDiagnostics.add(diagnostic); prevLineResult = LineParseResult::Ignore; break; } - case LineParseResult::Continuation: + case LineParseResult::Continuation: { - if (prevLineResult == LineParseResult::Start || prevLineResult == LineParseResult::Continuation) + if (prevLineResult == LineParseResult::Start || + prevLineResult == LineParseResult::Continuation) { if (workDiagnostics.getCount() > 0) { auto& last = workDiagnostics.getLast(); - // TODO(JS): Note that this is somewhat wasteful as every time we append we just allocate more memory - // to hold the result. - // If we had an allocator dedicated to 'text' we could perhaps just append to the end of the last allocation - // + // TODO(JS): Note that this is somewhat wasteful as every time we append we + // just allocate more memory to hold the result. If we had an allocator + // dedicated to 'text' we could perhaps just append to the end of the last + // allocation + // // We are now in a continuation, add to the last StringBuilder buf; buf.append(asStringSlice(last.text)); @@ -414,12 +433,12 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS } break; } - case LineParseResult::Ignore: + case LineParseResult::Ignore: { prevLineResult = lineRes; break; } - default: return SLANG_FAIL; + default: return SLANG_FAIL; } } @@ -428,7 +447,8 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS diagnostics->add(diagnostic); } - if (diagnostics->hasOfAtLeastSeverity(ArtifactDiagnostic::Severity::Error) || exeRes.resultCode != 0) + if (diagnostics->hasOfAtLeastSeverity(ArtifactDiagnostic::Severity::Error) || + exeRes.resultCode != 0) { diagnostics->setResult(SLANG_FAIL); } @@ -436,7 +456,11 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -/* static */SlangResult GCCDownstreamCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts) +/* static */ SlangResult GCCDownstreamCompilerUtil::calcCompileProducts( + const CompileOptions& options, + ProductFlags flags, + IOSFileArtifactRepresentation* lockFile, + List>& outArtifacts) { SLANG_ASSERT(options.modulePath.count); @@ -446,9 +470,13 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS { StringBuilder builder; const auto desc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType); - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, asStringSlice(options.modulePath), builder)); + SLANG_RETURN_ON_FAIL( + ArtifactDescUtil::calcPathForDesc(desc, asStringSlice(options.modulePath), builder)); - auto fileRep = OSFileArtifactRepresentation::create(IOSFileArtifactRepresentation::Kind::Owned, builder.getUnownedSlice(), lockFile); + auto fileRep = OSFileArtifactRepresentation::create( + IOSFileArtifactRepresentation::Kind::Owned, + builder.getUnownedSlice(), + lockFile); auto artifact = ArtifactUtil::createArtifact(desc); artifact->addRepresentation(fileRep); @@ -458,12 +486,16 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -/* static */SlangResult GCCDownstreamCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine) +/* static */ SlangResult GCCDownstreamCompilerUtil::calcArgs( + const CompileOptions& options, + CommandLine& cmdLine) { SLANG_ASSERT(options.modulePath.count); - PlatformKind platformKind = (options.platform == PlatformKind::Unknown) ? PlatformUtil::getPlatformKind() : options.platform; - + PlatformKind platformKind = (options.platform == PlatformKind::Unknown) + ? PlatformUtil::getPlatformKind() + : options.platform; + const auto targetDesc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType); if (options.sourceLanguage == SLANG_SOURCE_LANGUAGE_CPP) @@ -473,7 +505,7 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS // C++17 since we share headers with slang itself (which uses c++17) cmdLine.addArg("-std=c++17"); } - + if (targetDesc.payload == ArtifactDesc::Payload::MetalAIR) { cmdLine.addArg("-std=metal3.1"); @@ -484,44 +516,44 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS // speaking UB, and GCC 10+ is happy to take advantage of this, stop it. cmdLine.addArg("-fno-strict-aliasing"); - // TODO(JS): Here we always set -m32 on x86. It could be argued it is only necessary when creating a shared library - // but if we create an object file, we don't know what to choose because we don't know what final usage is. - // It could also be argued that the platformKind could define the actual desired target - but as it stands - // we only have a target of 'Linux' (as opposed to Win32/64). Really it implies we need an arch enumeration too. + // TODO(JS): Here we always set -m32 on x86. It could be argued it is only necessary when + // creating a shared library but if we create an object file, we don't know what to choose + // because we don't know what final usage is. It could also be argued that the platformKind + // could define the actual desired target - but as it stands we only have a target of 'Linux' + // (as opposed to Win32/64). Really it implies we need an arch enumeration too. // - // For now we just make X86 binaries try and produce x86 compatible binaries as fixes the immediate problems. + // For now we just make X86 binaries try and produce x86 compatible binaries as fixes the + // immediate problems. #if SLANG_PROCESSOR_X86 - /* Used to specify the processor more broadly. For a x86 binary we need to make sure we build x86 builds - even when on an x64 system. - -m32 - -m64*/ + /* Used to specify the processor more broadly. For a x86 binary we need to make sure we build + x86 builds even when on an x64 system. -m32 -m64*/ cmdLine.addArg("-m32"); #endif switch (options.optimizationLevel) { - case OptimizationLevel::None: + case OptimizationLevel::None: { // No optimization cmdLine.addArg("-O0"); break; } - case OptimizationLevel::Default: + case OptimizationLevel::Default: { cmdLine.addArg("-Os"); break; } - case OptimizationLevel::High: + case OptimizationLevel::High: { cmdLine.addArg("-O2"); break; } - case OptimizationLevel::Maximal: + case OptimizationLevel::Maximal: { cmdLine.addArg("-O4"); break; } - default: break; + default: break; } if (options.debugInfoType != DebugInfoType::None) @@ -536,31 +568,35 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS switch (options.floatingPointMode) { - case FloatingPointMode::Default: break; - case FloatingPointMode::Precise: + case FloatingPointMode::Default: break; + case FloatingPointMode::Precise: { - //cmdLine.addArg("-fno-unsafe-math-optimizations"); + // cmdLine.addArg("-fno-unsafe-math-optimizations"); break; } - case FloatingPointMode::Fast: + case FloatingPointMode::Fast: { // We could enable SSE with -mfpmath=sse - // But that would only make sense on a x64/x86 type processor and only if that feature is present (it is on all x64) + // But that would only make sense on a x64/x86 type processor and only if that feature + // is present (it is on all x64) cmdLine.addArg("-ffast-math"); break; } } - StringBuilder moduleFilePath; - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(targetDesc, asStringSlice(options.modulePath), moduleFilePath)); - + StringBuilder moduleFilePath; + SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc( + targetDesc, + asStringSlice(options.modulePath), + moduleFilePath)); + cmdLine.addArg("-o"); cmdLine.addArg(moduleFilePath); switch (options.targetType) { - case SLANG_SHADER_SHARED_LIBRARY: - case SLANG_HOST_SHARED_LIBRARY: + case SLANG_SHADER_SHARED_LIBRARY: + case SLANG_HOST_SHARED_LIBRARY: { // Shared library cmdLine.addArg("-shared"); @@ -572,18 +608,18 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS } break; } - case SLANG_HOST_EXECUTABLE: + case SLANG_HOST_EXECUTABLE: { cmdLine.addArg("-rdynamic"); break; } - case SLANG_OBJECT_CODE: + case SLANG_OBJECT_CODE: { // Don't link, just produce object file cmdLine.addArg("-c"); break; } - default: break; + default: break; } // Add defines @@ -611,8 +647,8 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS // Link options if (0) // && options.targetType != TargetType::Object) { - //linkOptions << "-Wl,"; - //cmdLine.addArg(linkOptions); + // linkOptions << "-Wl,"; + // cmdLine.addArg(linkOptions); } if (options.targetType == SLANG_SHADER_SHARED_LIBRARY) @@ -632,7 +668,7 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS { ComPtr fileRep; - // TODO(JS): + // TODO(JS): // Do we want to keep the file on the file system? It's probably reasonable to do so. SLANG_RETURN_ON_FAIL(sourceArtifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef())); cmdLine.addArg(fileRep->getPath()); @@ -640,10 +676,9 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS // Add the library paths - if (options.libraryPaths.count && - (options.targetType == SLANG_HOST_EXECUTABLE)) + if (options.libraryPaths.count && (options.targetType == SLANG_HOST_EXECUTABLE)) { - if(PlatformUtil::isFamily(PlatformFamily::Apple, platformKind)) + if (PlatformUtil::isFamily(PlatformFamily::Apple, platformKind)) cmdLine.addArg("-Wl,-rpath,@loader_path,-rpath,@loader_path/../lib"); else cmdLine.addArg("-Wl,-rpath,$ORIGIN,-rpath,$ORIGIN/../lib"); @@ -661,7 +696,8 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS { const auto artifactDesc = artifact->getDesc(); // If it's a library for CPU types, try and use it - if (ArtifactDescUtil::isCpuBinary(artifactDesc) && artifactDesc.kind == ArtifactKind::Library) + if (ArtifactDescUtil::isCpuBinary(artifactDesc) && + artifactDesc.kind == ArtifactKind::Library) { ComPtr fileRep; @@ -670,12 +706,15 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS const UnownedStringSlice path(fileRep->getPath()); libPathPool.add(Path::getParentDirectory(path)); - - cmdLine.addPrefixPathArg("-l", ArtifactDescUtil::getBaseNameFromPath(artifact->getDesc(), path)); + + cmdLine.addPrefixPathArg( + "-l", + ArtifactDescUtil::getBaseNameFromPath(artifact->getDesc(), path)); } } - if (options.sourceLanguage == SLANG_SOURCE_LANGUAGE_CPP && !PlatformUtil::isFamily(PlatformFamily::Windows, platformKind)) + if (options.sourceLanguage == SLANG_SOURCE_LANGUAGE_CPP && + !PlatformUtil::isFamily(PlatformFamily::Windows, platformKind)) { // Make STD libs available cmdLine.addArg("-lstdc++"); @@ -695,7 +734,9 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -/* static */SlangResult GCCDownstreamCompilerUtil::createCompiler(const ExecutableLocation& exe, ComPtr& outCompiler) +/* static */ SlangResult GCCDownstreamCompilerUtil::createCompiler( + const ExecutableLocation& exe, + ComPtr& outCompiler) { DownstreamCompilerDesc desc; SLANG_RETURN_ON_FAIL(GCCDownstreamCompilerUtil::calcVersion(exe, desc)); @@ -708,7 +749,10 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -/* static */SlangResult GCCDownstreamCompilerUtil::locateGCCCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult GCCDownstreamCompilerUtil::locateGCCCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { SLANG_UNUSED(loader); @@ -717,10 +761,10 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS { // A downstream compiler for Slang must currently support C++17 - such that // the prelude and generated code works. - // + // // The first version of gcc that supports stable `-std=c++17` is 9.0 // https://gcc.gnu.org/projects/cxx-status.html - + auto desc = compiler->getDesc(); if (desc.version.m_major < 9) { @@ -733,7 +777,10 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -/* static */SlangResult GCCDownstreamCompilerUtil::locateClangCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult GCCDownstreamCompilerUtil::locateClangCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { SLANG_UNUSED(loader); @@ -745,4 +792,4 @@ static SlangResult _parseGCCFamilyLine(SliceAllocator& allocator, const UnownedS return SLANG_OK; } -} +} // namespace Slang diff --git a/source/compiler-core/slang-gcc-compiler-util.h b/source/compiler-core/slang-gcc-compiler-util.h index 6afb39ec6..e15701f94 100644 --- a/source/compiler-core/slang-gcc-compiler-util.h +++ b/source/compiler-core/slang-gcc-compiler-util.h @@ -9,30 +9,46 @@ namespace Slang /* Utility for processing input and output of gcc-like compilers, including clang */ struct GCCDownstreamCompilerUtil : public DownstreamCompilerUtilBase { - /// Extracts version number into desc from text (assumes gcc/clang -v layout with a line with version) - static SlangResult parseVersion(const UnownedStringSlice& text, const UnownedStringSlice& prefix, DownstreamCompilerDesc& outDesc); + /// Extracts version number into desc from text (assumes gcc/clang -v layout with a line with + /// version) + static SlangResult parseVersion( + const UnownedStringSlice& text, + const UnownedStringSlice& prefix, + DownstreamCompilerDesc& outDesc); - /// Runs the exe, and extracts the version info into outDesc + /// Runs the exe, and extracts the version info into outDesc static SlangResult calcVersion(const ExecutableLocation& exe, DownstreamCompilerDesc& outDesc); - /// Calculate gcc family compilers (including clang) cmdLine arguments from options + /// Calculate gcc family compilers (including clang) cmdLine arguments from options static SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine); - /// Parse ExecuteResult into diagnostics + /// Parse ExecuteResult into diagnostics static SlangResult parseOutput(const ExecuteResult& exeRes, IArtifactDiagnostics* diagnostics); - /// Given options, calculate paths to products/files produced for a compilation - static SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags flags, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts); + /// Given options, calculate paths to products/files produced for a compilation + static SlangResult calcCompileProducts( + const CompileOptions& options, + ProductFlags flags, + IOSFileArtifactRepresentation* lockFile, + List>& outArtifacts); - /// Given the exe location, creates a DownstreamCompiler. - /// Note! Invoke/s the compiler to determine the compiler version number. - static SlangResult createCompiler(const ExecutableLocation& exe, ComPtr& outCompiler); + /// Given the exe location, creates a DownstreamCompiler. + /// Note! Invoke/s the compiler to determine the compiler version number. + static SlangResult createCompiler( + const ExecutableLocation& exe, + ComPtr& outCompiler); - /// Finds GCC compiler/s and adds them to the set - static SlangResult locateGCCCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + /// Finds GCC compiler/s and adds them to the set + static SlangResult locateGCCCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); - /// Finds clang compiler/s and adds them to the set - static SlangResult locateClangCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + /// Finds clang compiler/s and adds them to the set + static SlangResult locateClangCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; class GCCDownstreamCompiler : public CommandLineDownstreamCompiler @@ -42,13 +58,31 @@ public: typedef GCCDownstreamCompilerUtil Util; // CommandLineCPPCompiler impl - just forwards to the Util - virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) SLANG_OVERRIDE { return Util::calcArgs(options, cmdLine); } - virtual SlangResult parseOutput(const ExecuteResult& exeResult, IArtifactDiagnostics* diagnostics) SLANG_OVERRIDE { return Util::parseOutput(exeResult, diagnostics); } - virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags flags, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts) SLANG_OVERRIDE { return Util::calcCompileProducts(options, flags, lockFile, outArtifacts); } + virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) SLANG_OVERRIDE + { + return Util::calcArgs(options, cmdLine); + } + virtual SlangResult parseOutput( + const ExecuteResult& exeResult, + IArtifactDiagnostics* diagnostics) SLANG_OVERRIDE + { + return Util::parseOutput(exeResult, diagnostics); + } + virtual SlangResult calcCompileProducts( + const CompileOptions& options, + DownstreamProductFlags flags, + IOSFileArtifactRepresentation* lockFile, + List>& outArtifacts) SLANG_OVERRIDE + { + return Util::calcCompileProducts(options, flags, lockFile, outArtifacts); + } - GCCDownstreamCompiler(const Desc& desc):Super(desc) {} + GCCDownstreamCompiler(const Desc& desc) + : Super(desc) + { + } }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-glslang-compiler.cpp b/source/compiler-core/slang-glslang-compiler.cpp index 54635873a..fd80c7581 100644 --- a/source/compiler-core/slang-glslang-compiler.cpp +++ b/source/compiler-core/slang-glslang-compiler.cpp @@ -1,35 +1,28 @@ // slang-glslang-compiler.cpp #include "slang-glslang-compiler.h" -#include "../core/slang-common.h" -#include "slang-com-helper.h" - #include "../core/slang-blob.h" - -#include "../core/slang-string-util.h" -#include "../core/slang-string-slice-pool.h" - +#include "../core/slang-char-util.h" +#include "../core/slang-common.h" #include "../core/slang-io.h" -#include "../core/slang-shared-library.h" #include "../core/slang-semantic-version.h" -#include "../core/slang-char-util.h" - +#include "../core/slang-shared-library.h" +#include "../core/slang-string-slice-pool.h" +#include "../core/slang-string-util.h" #include "slang-artifact-associated-impl.h" #include "slang-artifact-desc-util.h" - +#include "slang-com-helper.h" #include "slang-include-system.h" #include "slang-source-loc.h" -#include "../core/slang-shared-library.h" - // Enable calling through to `glslang` on // all platforms. #ifndef SLANG_ENABLE_GLSLANG_SUPPORT -# define SLANG_ENABLE_GLSLANG_SUPPORT 1 +#define SLANG_ENABLE_GLSLANG_SUPPORT 1 #endif #if SLANG_ENABLE_GLSLANG_SUPPORT -# include "../slang-glslang/slang-glslang.h" +#include "../slang-glslang/slang-glslang.h" #endif namespace Slang @@ -43,24 +36,31 @@ public: typedef DownstreamCompilerBase Super; // IDownstreamCompiler - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outResult) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outResult) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; } - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL validate(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) + SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + validate(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE; - /// Must be called before use + /// Must be called before use SlangResult init(ISlangSharedLibrary* library); - GlslangDownstreamCompiler(SlangPassThrough compilerType) : m_compilerType(compilerType) {} - -protected: + GlslangDownstreamCompiler(SlangPassThrough compilerType) + : m_compilerType(compilerType) + { + } +protected: SlangResult _invoke(glslang_CompileRequest_1_2& request); - glslang_CompileFunc_1_0 m_compile_1_0 = nullptr; - glslang_CompileFunc_1_1 m_compile_1_1 = nullptr; + glslang_CompileFunc_1_0 m_compile_1_0 = nullptr; + glslang_CompileFunc_1_1 m_compile_1_1 = nullptr; glslang_CompileFunc_1_2 m_compile_1_2 = nullptr; glslang_ValidateSPIRVFunc m_validate = nullptr; @@ -135,7 +135,11 @@ SlangResult GlslangDownstreamCompiler::_invoke(glslang_CompileRequest_1_2& reque return err ? SLANG_FAIL : SLANG_OK; } -static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const UnownedStringSlice& line, List& lineSlices, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseDiagnosticLine( + SliceAllocator& allocator, + const UnownedStringSlice& line, + List& lineSlices, + ArtifactDiagnostic& outDiagnostic) { /* ERROR: tests/diagnostics/syntax-error-intrinsic.slang:13: '@' : unexpected token */ @@ -160,7 +164,9 @@ static SlangResult _parseDiagnosticLine(SliceAllocator& allocator, const Unowned return SLANG_OK; } -SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& inOptions, IArtifact** outArtifact) +SlangResult GlslangDownstreamCompiler::compile( + const CompileOptions& inOptions, + IArtifact** outArtifact) { if (!isVersionCompatible(inOptions)) { @@ -186,14 +192,10 @@ SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& inOptions, StringBuilder diagnosticOutput; auto diagnosticOutputFunc = [](void const* data, size_t size, void* userData) - { - (*(StringBuilder*)userData).append((char const*)data, (char const*)data + size); - }; + { (*(StringBuilder*)userData).append((char const*)data, (char const*)data + size); }; List spirv; auto outputFunc = [](void const* data, size_t size, void* userData) - { - ((List*)userData)->addRange((uint8_t*)data, size); - }; + { ((List*)userData)->addRange((uint8_t*)data, size); }; ComPtr sourceBlob; SLANG_RETURN_ON_FAIL(sourceArtifact->loadBlob(ArtifactKeep::Yes, sourceBlob.writeRef())); @@ -206,15 +208,9 @@ SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& inOptions, switch (options.sourceLanguage) { - case SLANG_SOURCE_LANGUAGE_GLSL: - request.action = GLSLANG_ACTION_COMPILE_GLSL_TO_SPIRV; - break; - case SLANG_SOURCE_LANGUAGE_SPIRV: - request.action = GLSLANG_ACTION_OPTIMIZE_SPIRV; - break; - default: - SLANG_ASSERT(!"Can only handle GLSL or SPIR-V as input."); - return SLANG_FAIL; + case SLANG_SOURCE_LANGUAGE_GLSL: request.action = GLSLANG_ACTION_COMPILE_GLSL_TO_SPIRV; break; + case SLANG_SOURCE_LANGUAGE_SPIRV: request.action = GLSLANG_ACTION_OPTIMIZE_SPIRV; break; + default: SLANG_ASSERT(!"Can only handle GLSL or SPIR-V as input."); return SLANG_FAIL; } request.sourcePath = sourcePath.getBuffer(); @@ -270,7 +266,12 @@ SlangResult GlslangDownstreamCompiler::compile(const CompileOptions& inOptions, SliceAllocator allocator; - SlangResult diagnosticParseRes = ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics(allocator, diagnosticOutput.getUnownedSlice(), 1, _parseDiagnosticLine, diagnostics); + SlangResult diagnosticParseRes = ArtifactDiagnosticUtil::parseColonDelimitedDiagnostics( + allocator, + diagnosticOutput.getUnownedSlice(), + 1, + _parseDiagnosticLine, + diagnostics); SLANG_UNUSED(diagnosticParseRes); diagnostics->requireErrorDiagnostic(); @@ -301,12 +302,15 @@ SlangResult GlslangDownstreamCompiler::validate(const uint32_t* contents, int co bool GlslangDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactDesc& to) { // Can only disassemble blobs that are SPIR-V - return ArtifactDescUtil::isDisassembly(from, to) && ( - (from.payload == ArtifactPayload::SPIRV) || - (from.payload == ArtifactPayload::WGSL_SPIRV)); + return ArtifactDescUtil::isDisassembly(from, to) && + ((from.payload == ArtifactPayload::SPIRV) || + (from.payload == ArtifactPayload::WGSL_SPIRV)); } -SlangResult GlslangDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) +SlangResult GlslangDownstreamCompiler::convert( + IArtifact* from, + const ArtifactDesc& to, + IArtifact** outArtifact) { if (!canConvert(from->getDesc(), to)) { @@ -317,11 +321,9 @@ SlangResult GlslangDownstreamCompiler::convert(IArtifact* from, const ArtifactDe SLANG_RETURN_ON_FAIL(from->loadBlob(ArtifactKeep::No, blob.writeRef())); StringBuilder builder; - + auto outputFunc = [](void const* data, size_t size, void* userData) - { - (*(StringBuilder*)userData).append((char const*)data, (char const*)data + size); - }; + { (*(StringBuilder*)userData).append((char const*)data, (char const*)data + size); }; glslang_CompileRequest_1_2 request; memset(&request, 0, sizeof(request)); @@ -366,14 +368,18 @@ SlangResult GlslangDownstreamCompiler::getVersionString(slang::IBlob** outVersio { return SLANG_FAIL; } - + auto timestampString = String(timestamp); ComPtr version = StringBlob::create(timestampString.getBuffer()); *outVersionString = version.detach(); return SLANG_OK; } -static SlangResult locateGlslangSpirvDownstreamCompiler(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set, SlangPassThrough compilerType) +static SlangResult locateGlslangSpirvDownstreamCompiler( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set, + SlangPassThrough compilerType) { ComPtr library; @@ -381,18 +387,23 @@ static SlangResult locateGlslangSpirvDownstreamCompiler(const String& path, ISla // On unix systems we need to ensure pthread is loaded first. // TODO(JS): // There is an argument that this should be performed through the loader.... - // NOTE! We don't currently load through a dependent library, as it is *assumed* something as core as 'ptheads' - // isn't going to be distributed with the shader compiler. + // NOTE! We don't currently load through a dependent library, as it is *assumed* something as + // core as 'ptheads' isn't going to be distributed with the shader compiler. ComPtr pthreadLibrary; DefaultSharedLibraryLoader::load(loader, path, "pthread", pthreadLibrary.writeRef()); if (!pthreadLibrary.get()) { - DefaultSharedLibraryLoader::load(loader, path, "libpthread.so.0", pthreadLibrary.writeRef()); + DefaultSharedLibraryLoader::load( + loader, + path, + "libpthread.so.0", + pthreadLibrary.writeRef()); } #endif - SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, "slang-glslang", library)); + SLANG_RETURN_ON_FAIL( + DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, "slang-glslang", library)); SLANG_ASSERT(library); if (!library) @@ -408,24 +419,36 @@ static SlangResult locateGlslangSpirvDownstreamCompiler(const String& path, ISla return SLANG_OK; } -SlangResult GlslangDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +SlangResult GlslangDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { return locateGlslangSpirvDownstreamCompiler(path, loader, set, SLANG_PASS_THROUGH_GLSLANG); } -SlangResult SpirvOptDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +SlangResult SpirvOptDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { return locateGlslangSpirvDownstreamCompiler(path, loader, set, SLANG_PASS_THROUGH_SPIRV_OPT); } -SlangResult SpirvDisDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +SlangResult SpirvDisDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { return locateGlslangSpirvDownstreamCompiler(path, loader, set, SLANG_PASS_THROUGH_SPIRV_DIS); } #else // SLANG_ENABLE_GLSLANG_SUPPORT -/* static */SlangResult GlslangDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult GlslangDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { SLANG_UNUSED(path); SLANG_UNUSED(loader); @@ -435,4 +458,4 @@ SlangResult SpirvDisDownstreamCompilerUtil::locateCompilers(const String& path, #endif // SLANG_ENABLE_GLSLANG_SUPPORT -} +} // namespace Slang diff --git a/source/compiler-core/slang-glslang-compiler.h b/source/compiler-core/slang-glslang-compiler.h index 577bcaacc..73cc61135 100644 --- a/source/compiler-core/slang-glslang-compiler.h +++ b/source/compiler-core/slang-glslang-compiler.h @@ -1,29 +1,37 @@ #ifndef SLANG_GLSLANG_COMPILER_UTIL_H #define SLANG_GLSLANG_COMPILER_UTIL_H -#include "slang-downstream-compiler-util.h" - #include "../core/slang-platform.h" +#include "slang-downstream-compiler-util.h" namespace Slang { struct GlslangDownstreamCompilerUtil { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; struct SpirvOptDownstreamCompilerUtil { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; struct SpirvDisDownstreamCompilerUtil { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-include-system.cpp b/source/compiler-core/slang-include-system.cpp index 1b768d506..4ee742136 100644 --- a/source/compiler-core/slang-include-system.cpp +++ b/source/compiler-core/slang-include-system.cpp @@ -1,26 +1,31 @@ // slang-include-system.cpp #include "slang-include-system.h" +#include "../core/slang-file-system.h" #include "../core/slang-io.h" #include "../core/slang-string-util.h" - -#include "../core/slang-file-system.h" - -#include "slang-slice-allocator.h" #include "slang-artifact-impl.h" #include "slang-artifact-representation-impl.h" +#include "slang-slice-allocator.h" namespace Slang { -IncludeSystem::IncludeSystem(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager) : - m_searchDirectories(searchDirectories), - m_fileSystemExt(fileSystemExt), - m_sourceManager(sourceManager) +IncludeSystem::IncludeSystem( + SearchDirectoryList* searchDirectories, + ISlangFileSystemExt* fileSystemExt, + SourceManager* sourceManager) + : m_searchDirectories(searchDirectories) + , m_fileSystemExt(fileSystemExt) + , m_sourceManager(sourceManager) { } -SlangResult IncludeSystem::findFile(SlangPathType fromPathType, const String& fromPath, const String& path, PathInfo& outPathInfo) +SlangResult IncludeSystem::findFile( + SlangPathType fromPathType, + const String& fromPath, + const String& path, + PathInfo& outPathInfo) { String combinedPath; @@ -33,7 +38,11 @@ SlangResult IncludeSystem::findFile(SlangPathType fromPathType, const String& fr { // Get relative path ComPtr combinedPathBlob; - SLANG_RETURN_ON_FAIL(m_fileSystemExt->calcCombinedPath(fromPathType, fromPath.begin(), path.begin(), combinedPathBlob.writeRef())); + SLANG_RETURN_ON_FAIL(m_fileSystemExt->calcCombinedPath( + fromPathType, + fromPath.begin(), + path.begin(), + combinedPathBlob.writeRef())); combinedPath = StringUtil::getString(combinedPathBlob); if (combinedPath.getLength() <= 0) { @@ -51,7 +60,9 @@ SlangResult IncludeSystem::findFile(SlangPathType fromPathType, const String& fr // Get the uniqueIdentity ComPtr uniqueIdentityBlob; - SLANG_RETURN_ON_FAIL(m_fileSystemExt->getFileUniqueIdentity(combinedPath.begin(), uniqueIdentityBlob.writeRef())); + SLANG_RETURN_ON_FAIL(m_fileSystemExt->getFileUniqueIdentity( + combinedPath.begin(), + uniqueIdentityBlob.writeRef())); // If the rel path exists -> a uniqueIdentity MUST exists too String uniqueIdentity(StringUtil::getString(uniqueIdentityBlob)); @@ -68,14 +79,20 @@ SlangResult IncludeSystem::findFile(SlangPathType fromPathType, const String& fr String IncludeSystem::simplifyPath(const String& path) { ComPtr simplifiedPath; - if (SLANG_FAILED(m_fileSystemExt->getPath(PathKind::Simplified, path.getBuffer(), simplifiedPath.writeRef()))) + if (SLANG_FAILED(m_fileSystemExt->getPath( + PathKind::Simplified, + path.getBuffer(), + simplifiedPath.writeRef()))) { return path; } return StringUtil::getString(simplifiedPath); } -SlangResult IncludeSystem::findFile(String const& pathToInclude, String const& pathIncludedFrom, PathInfo& outPathInfo) +SlangResult IncludeSystem::findFile( + String const& pathToInclude, + String const& pathIncludedFrom, + PathInfo& outPathInfo) { outPathInfo.type = PathInfo::Type::Unknown; @@ -84,12 +101,17 @@ SlangResult IncludeSystem::findFile(String const& pathToInclude, String const& p { // We pass in "" as the from path, so ensure no from path is taken into account // and to allow easy identification that this is in effect absolute - return findFile(SLANG_PATH_TYPE_DIRECTORY, UnownedStringSlice::fromLiteral(""), pathToInclude, outPathInfo); + return findFile( + SLANG_PATH_TYPE_DIRECTORY, + UnownedStringSlice::fromLiteral(""), + pathToInclude, + outPathInfo); } // Try just relative to current path { - SlangResult res = findFile(SLANG_PATH_TYPE_FILE, pathIncludedFrom, pathToInclude, outPathInfo); + SlangResult res = + findFile(SLANG_PATH_TYPE_FILE, pathIncludedFrom, pathToInclude, outPathInfo); // It either succeeded or wasn't found, anything else is a failure passed back if (SLANG_SUCCEEDED(res) || res != SLANG_E_NOT_FOUND) { @@ -102,7 +124,8 @@ SlangResult IncludeSystem::findFile(String const& pathToInclude, String const& p { for (auto& dir : sd->searchDirectories) { - SlangResult res = findFile(SLANG_PATH_TYPE_DIRECTORY, dir.path, pathToInclude, outPathInfo); + SlangResult res = + findFile(SLANG_PATH_TYPE_DIRECTORY, dir.path, pathToInclude, outPathInfo); if (SLANG_SUCCEEDED(res) || res != SLANG_E_NOT_FOUND) { return res; @@ -113,7 +136,10 @@ SlangResult IncludeSystem::findFile(String const& pathToInclude, String const& p return SLANG_E_NOT_FOUND; } -SlangResult IncludeSystem::loadFile(const PathInfo& pathInfo, ComPtr& outBlob, SourceFile*& outSourceFile) +SlangResult IncludeSystem::loadFile( + const PathInfo& pathInfo, + ComPtr& outBlob, + SourceFile*& outSourceFile) { if (m_sourceManager) { @@ -124,7 +150,9 @@ SlangResult IncludeSystem::loadFile(const PathInfo& pathInfo, ComPtr if (!outSourceFile) { ComPtr foundSourceBlob; - if (SLANG_FAILED(m_fileSystemExt->loadFile(pathInfo.foundPath.getBuffer(), foundSourceBlob.writeRef()))) + if (SLANG_FAILED(m_fileSystemExt->loadFile( + pathInfo.foundPath.getBuffer(), + foundSourceBlob.writeRef()))) { return SLANG_E_CANNOT_OPEN; } @@ -144,7 +172,9 @@ SlangResult IncludeSystem::loadFile(const PathInfo& pathInfo, ComPtr } ComPtr foundSourceBlob; - if (SLANG_FAILED(m_fileSystemExt->loadFile(pathInfo.foundPath.getBuffer(), foundSourceBlob.writeRef()))) + if (SLANG_FAILED(m_fileSystemExt->loadFile( + pathInfo.foundPath.getBuffer(), + foundSourceBlob.writeRef()))) { return SLANG_E_CANNOT_OPEN; } @@ -163,7 +193,11 @@ SlangResult IncludeSystem::loadFile(const PathInfo& pathInfo, ComPtr } } -SlangResult IncludeSystem::findAndLoadFile(const String& pathToInclude, const String& pathIncludedFrom, PathInfo& outPathInfo, ComPtr& outBlob) +SlangResult IncludeSystem::findAndLoadFile( + const String& pathToInclude, + const String& pathIncludedFrom, + PathInfo& outPathInfo, + ComPtr& outBlob) { SLANG_RETURN_ON_FAIL(findFile(pathToInclude, pathIncludedFrom, outPathInfo)); SLANG_RETURN_ON_FAIL(loadFile(outPathInfo, outBlob)); diff --git a/source/compiler-core/slang-include-system.h b/source/compiler-core/slang-include-system.h index cc89985dd..dbe3793bf 100644 --- a/source/compiler-core/slang-include-system.h +++ b/source/compiler-core/slang-include-system.h @@ -14,7 +14,8 @@ struct SearchDirectory SearchDirectory(SearchDirectory const& other) = default; SearchDirectory(String const& path) : path(path) - {} + { + } SearchDirectory& operator=(SearchDirectory const& other) = default; String path; @@ -24,42 +25,60 @@ struct SearchDirectory struct SearchDirectoryList { // A parent list that should also be searched - SearchDirectoryList* parent = nullptr; + SearchDirectoryList* parent = nullptr; // Directories to be searched - List searchDirectories; + List searchDirectories; }; -/* A helper class that builds basic include handling on top of searchDirectories/fileSystemExt and optionally a sourceManager */ +/* A helper class that builds basic include handling on top of searchDirectories/fileSystemExt and + * optionally a sourceManager */ struct IncludeSystem { - SlangResult findFile(const String& pathToInclude, const String& pathIncludedFrom, PathInfo& outPathInfo); - SlangResult findFile(SlangPathType fromPathType, const String& fromPath, const String& path, PathInfo& outPathInfo); + SlangResult findFile( + const String& pathToInclude, + const String& pathIncludedFrom, + PathInfo& outPathInfo); + SlangResult findFile( + SlangPathType fromPathType, + const String& fromPath, + const String& path, + PathInfo& outPathInfo); String simplifyPath(const String& path); - SlangResult loadFile(const PathInfo& pathInfo, ComPtr& outBlob, SourceFile*& outSourceFile); + SlangResult loadFile( + const PathInfo& pathInfo, + ComPtr& outBlob, + SourceFile*& outSourceFile); inline SlangResult loadFile(const PathInfo& pathInfo, ComPtr& outBlob) { SourceFile* sourceFile; return loadFile(pathInfo, outBlob, sourceFile); } - SlangResult findAndLoadFile(const String& pathToInclude, const String& pathIncludedFrom, PathInfo& outPathInfo, ComPtr& outBlob); + SlangResult findAndLoadFile( + const String& pathToInclude, + const String& pathIncludedFrom, + PathInfo& outPathInfo, + ComPtr& outBlob); SearchDirectoryList* getSearchDirectoryList() const { return m_searchDirectories; } ISlangFileSystemExt* getFileSystem() const { return m_fileSystemExt; } SourceManager* getSourceManager() const { return m_sourceManager; } - /// Ctor + /// Ctor IncludeSystem() = default; - IncludeSystem(SearchDirectoryList* searchDirectories, ISlangFileSystemExt* fileSystemExt, SourceManager* sourceManager = nullptr); + IncludeSystem( + SearchDirectoryList* searchDirectories, + ISlangFileSystemExt* fileSystemExt, + SourceManager* sourceManager = nullptr); protected: - SearchDirectoryList* m_searchDirectories; ISlangFileSystemExt* m_fileSystemExt; - SourceManager* m_sourceManager; ///< If not set, will not look up the content in the source manager + SourceManager* + m_sourceManager; ///< If not set, will not look up the content in the source manager }; -} +} // namespace Slang -#endif // SLANG_INCLUDE_HANDLER_H +#endif // SLANG_INCLUDE_HANDLER_H diff --git a/source/compiler-core/slang-json-diagnostic-defs.h b/source/compiler-core/slang-json-diagnostic-defs.h index 576f14beb..2bc4c6a81 100644 --- a/source/compiler-core/slang-json-diagnostic-defs.h +++ b/source/compiler-core/slang-json-diagnostic-defs.h @@ -14,7 +14,7 @@ // for any arguments. #ifndef DIAGNOSTIC -#error Need to #define DIAGNOSTIC(...) before including +#error Need to #define DIAGNOSTIC(...) before including #define DIAGNOSTIC(id, severity, name, messageFormat) /* */ #endif @@ -40,7 +40,11 @@ DIAGNOSTIC(20009, Error, unableToConvertField, "unable to convert field '$0' in DIAGNOSTIC(20010, Error, fieldNotFound, "field '$0' not found in type '$1'") DIAGNOSTIC(20011, Error, fieldNotDefinedOnType, "field '$0' not defined on type '$1'") DIAGNOSTIC(20011, Error, fieldRequiredOnType, "field '$0' required on '$1'") -DIAGNOSTIC(20012, Error, tooManyElementsForArray, "too many elements ($0) for array array. Max allowed is $1") +DIAGNOSTIC( + 20012, + Error, + tooManyElementsForArray, + "too many elements ($0) for array array. Max allowed is $1") // // 3xxxx JSON-RPC diff --git a/source/compiler-core/slang-json-diagnostics.cpp b/source/compiler-core/slang-json-diagnostics.cpp index 1d35e8faf..1dc30572e 100644 --- a/source/compiler-core/slang-json-diagnostics.cpp +++ b/source/compiler-core/slang-json-diagnostics.cpp @@ -1,18 +1,19 @@ // slang-json-diagnostics.cpp #include "slang-json-diagnostics.h" -namespace Slang { +namespace Slang +{ namespace JSONDiagnostics { -#define DIAGNOSTIC(id, severity, name, messageFormat) const DiagnosticInfo name = { id, Severity::severity, #name, messageFormat }; +#define DIAGNOSTIC(id, severity, name, messageFormat) \ + const DiagnosticInfo name = {id, Severity::severity, #name, messageFormat}; #include "slang-json-diagnostic-defs.h" #undef DIAGNOSTIC -} +} // namespace JSONDiagnostics -static const DiagnosticInfo* const kJSONDiagnostics[] = -{ -#define DIAGNOSTIC(id, severity, name, messageFormat) &JSONDiagnostics::name, +static const DiagnosticInfo* const kJSONDiagnostics[] = { +#define DIAGNOSTIC(id, severity, name, messageFormat) &JSONDiagnostics::name, #include "slang-json-diagnostic-defs.h" #undef DIAGNOSTIC }; diff --git a/source/compiler-core/slang-json-diagnostics.h b/source/compiler-core/slang-json-diagnostics.h index d819d8947..183178d2b 100644 --- a/source/compiler-core/slang-json-diagnostics.h +++ b/source/compiler-core/slang-json-diagnostics.h @@ -3,11 +3,9 @@ #include "../core/slang-basic.h" #include "../core/slang-writer.h" - -#include "slang-source-loc.h" #include "slang-diagnostic-sink.h" +#include "slang-source-loc.h" #include "slang-token.h" - #include "slang.h" namespace Slang @@ -19,8 +17,8 @@ namespace JSONDiagnostics { #define DIAGNOSTIC(id, severity, name, messageFormat) extern const DiagnosticInfo name; #include "slang-json-diagnostic-defs.h" -} +} // namespace JSONDiagnostics -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-json-lexer.cpp b/source/compiler-core/slang-json-lexer.cpp index a335403e1..84b6b24bc 100644 --- a/source/compiler-core/slang-json-lexer.cpp +++ b/source/compiler-core/slang-json-lexer.cpp @@ -1,16 +1,17 @@ // slang-json-lexer.cpp #include "slang-json-lexer.h" -#include "slang-json-diagnostics.h" #include "../core/slang-char-util.h" +#include "slang-json-diagnostics.h" /* https://www.json.org/json-en.html */ -namespace Slang { +namespace Slang +{ -/* static */UnownedStringSlice JSONLexer::calcLexemeLocation(const UnownedStringSlice& text) +/* static */ UnownedStringSlice JSONLexer::calcLexemeLocation(const UnownedStringSlice& text) { SourceManager sourceManager; sourceManager.initialize(nullptr, nullptr); @@ -18,7 +19,8 @@ namespace Slang { sink.init(&sourceManager, nullptr); String contents(text); - SourceFile* sourceFile = sourceManager.createSourceFileWithString(PathInfo::makeUnknown(), contents); + SourceFile* sourceFile = + sourceManager.createSourceFileWithString(PathInfo::makeUnknown(), contents); SourceView* sourceView = sourceManager.createSourceView(sourceFile, nullptr, SourceLoc()); JSONLexer lexer; @@ -38,7 +40,7 @@ namespace Slang { } } -SlangResult JSONLexer::init(SourceView* sourceView, DiagnosticSink* sink) +SlangResult JSONLexer::init(SourceView* sourceView, DiagnosticSink* sink) { m_sourceView = sourceView; m_sink = sink; @@ -77,7 +79,11 @@ SlangResult JSONLexer::expect(JSONTokenType type) { if (type != peekType()) { - m_sink->diagnose(m_token.loc, JSONDiagnostics::unexpectedTokenExpectedTokenType, getJSONTokenAsText(peekType()), getJSONTokenAsText(type)); + m_sink->diagnose( + m_token.loc, + JSONDiagnostics::unexpectedTokenExpectedTokenType, + getJSONTokenAsText(peekType()), + getJSONTokenAsText(type)); return SLANG_FAIL; } @@ -89,7 +95,11 @@ SlangResult JSONLexer::expect(JSONTokenType type, JSONToken& out) { if (type != peekType()) { - m_sink->diagnose(m_token.loc, JSONDiagnostics::unexpectedTokenExpectedTokenType, getJSONTokenAsText(peekType()), getJSONTokenAsText(type)); + m_sink->diagnose( + m_token.loc, + JSONDiagnostics::unexpectedTokenExpectedTokenType, + getJSONTokenAsText(peekType()), + getJSONTokenAsText(type)); return SLANG_FAIL; } @@ -137,8 +147,8 @@ JSONTokenType JSONLexer::advance() switch (c) { - case 0: return _setToken(JSONTokenType::EndOfFile, cursor - 1); - case '"': + case 0: return _setToken(JSONTokenType::EndOfFile, cursor - 1); + case '"': { cursor = _lexString(cursor); if (cursor == nullptr) @@ -147,7 +157,7 @@ JSONTokenType JSONLexer::advance() } return _setToken(JSONTokenType::StringLiteral, cursor); } - case '/': + case '/': { // We allow comments const char nextChar = *m_cursor; @@ -160,7 +170,7 @@ JSONTokenType JSONLexer::advance() else if (nextChar == '*') { cursor = _lexBlockComment(cursor); - // Can fail... + // Can fail... if (cursor == nullptr) { return _setInvalidToken(); @@ -172,32 +182,32 @@ JSONTokenType JSONLexer::advance() } break; } - case ' ': - case '\t': - case '\n': - case '\r': + case ' ': + case '\t': + case '\n': + case '\r': { cursor = _lexWhitespace(cursor); break; } - case ':': return _setToken(JSONTokenType::Colon, cursor); - case ',': return _setToken(JSONTokenType::Comma, cursor); - case '[': return _setToken(JSONTokenType::LBracket, cursor); - case ']': return _setToken(JSONTokenType::RBracket, cursor); - case '{': return _setToken(JSONTokenType::LBrace, cursor); - case '}': return _setToken(JSONTokenType::RBrace, cursor); - - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': + case ':': return _setToken(JSONTokenType::Colon, cursor); + case ',': return _setToken(JSONTokenType::Comma, cursor); + case '[': return _setToken(JSONTokenType::LBracket, cursor); + case ']': return _setToken(JSONTokenType::RBracket, cursor); + case '{': return _setToken(JSONTokenType::LBrace, cursor); + case '}': return _setToken(JSONTokenType::RBrace, cursor); + + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { LexResult res = _lexNumber(cursor - 1); if (res.cursor == nullptr) @@ -206,7 +216,7 @@ JSONTokenType JSONLexer::advance() } return _setToken(res.type, res.cursor); } - case 't': + case 't': { if (cursor[0] == 'r' && cursor[1] == 'u' && cursor[2] == 'e') { @@ -215,7 +225,7 @@ JSONTokenType JSONLexer::advance() m_sink->diagnose(_getLoc(m_lexemeStart), JSONDiagnostics::expectingValueName); return _setInvalidToken(); } - case 'f': + case 'f': { if (cursor[0] == 'a' && cursor[1] == 'l' && cursor[2] == 's' && cursor[3] == 'e') { @@ -224,7 +234,7 @@ JSONTokenType JSONLexer::advance() m_sink->diagnose(_getLoc(m_lexemeStart), JSONDiagnostics::expectingValueName); return _setInvalidToken(); } - case 'n': + case 'n': { if (cursor[0] == 'u' && cursor[1] == 'l' && cursor[2] == 'l') { @@ -233,7 +243,7 @@ JSONTokenType JSONLexer::advance() m_sink->diagnose(_getLoc(m_lexemeStart), JSONDiagnostics::expectingValueName); return _setInvalidToken(); } - default: + default: { StringBuilder buf; if (c <= ' ' || c >= 0x7e) @@ -241,7 +251,7 @@ JSONTokenType JSONLexer::advance() static const char s_hex[] = "0123456789abcdef"; char hexBuf[5] = "0x"; - + uint32_t value = c; hexBuf[2] = s_hex[((value >> 4) & 0xf)]; hexBuf[3] = s_hex[(value & 0xf)]; @@ -294,12 +304,13 @@ JSONLexer::LexResult JSONLexer::_lexNumber(const char* cursor) if (!CharUtil::isDigit(*cursor)) { m_sink->diagnose(_getLoc(cursor), JSONDiagnostics::expectingADigit); - return LexResult{ JSONTokenType::Invalid, nullptr }; + return LexResult{JSONTokenType::Invalid, nullptr}; } // Skip the digit cursor++; // Skip any more digits - while (CharUtil::isDigit(*cursor)) cursor++; + while (CharUtil::isDigit(*cursor)) + cursor++; } // Theres an exponent @@ -320,13 +331,14 @@ JSONLexer::LexResult JSONLexer::_lexNumber(const char* cursor) if (!CharUtil::isDigit(*cursor)) { m_sink->diagnose(_getLoc(cursor), JSONDiagnostics::expectingADigit); - return LexResult{ JSONTokenType::Invalid, nullptr }; + return LexResult{JSONTokenType::Invalid, nullptr}; } // Skip the digit cursor++; // Skip any more digits - while (CharUtil::isDigit(*cursor)) cursor++; + while (CharUtil::isDigit(*cursor)) + cursor++; } return LexResult{tokenType, cursor}; @@ -341,40 +353,42 @@ const char* JSONLexer::_lexString(const char* cursor) switch (c) { - case 0: + case 0: { m_sink->diagnose(_getLoc(cursor - 1), JSONDiagnostics::endOfFileInLiteral); return nullptr; } - case '"': + case '"': { return cursor; } - case '\\': + case '\\': { const char nextC = *cursor; switch (nextC) { - case '"': - case '\\': - case '/': - case 'b': - case 'f': - case 'n': - case 'r': - case 't': + case '"': + case '\\': + case '/': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': { ++cursor; break; } - case 'u': + case 'u': { cursor++; for (Index i = 0; i < 4; ++i) { if (!CharUtil::isHexDigit(cursor[i])) { - m_sink->diagnose(_getLoc(cursor), JSONDiagnostics::expectingAHexDigit); + m_sink->diagnose( + _getLoc(cursor), + JSONDiagnostics::expectingAHexDigit); return nullptr; } } @@ -382,10 +396,9 @@ const char* JSONLexer::_lexString(const char* cursor) break; } } - } - // Somewhat surprisingly it appears it's valid to have \r\n inside of quotes. - default: break; + // Somewhat surprisingly it appears it's valid to have \r\n inside of quotes. + default: break; } } } @@ -398,13 +411,13 @@ const char* JSONLexer::_lexLineComment(const char* cursor) switch (c) { - case '\n': - case '\r': + case '\n': + case '\r': { // We need to skip to the next line return _handleEndOfLine(c, cursor); } - case 0: + case 0: { return cursor - 1; } @@ -419,12 +432,12 @@ const char* JSONLexer::_lexBlockComment(const char* cursor) const char c = *cursor++; switch (c) { - case 0: + case 0: { m_sink->diagnose(_getLoc(cursor), JSONDiagnostics::endOfFileInComment); return nullptr; } - case '*': + case '*': { if (*cursor == '/') { @@ -432,7 +445,7 @@ const char* JSONLexer::_lexBlockComment(const char* cursor) } break; } - default: break; + default: break; } } } @@ -447,21 +460,20 @@ const char* JSONLexer::_lexWhitespace(const char* cursor) switch (c) { - case ' ': - case '\n': - case '\r': - case '\t': + case ' ': + case '\n': + case '\r': + case '\t': { cursor++; break; } - default: + default: { // Hit non white space return cursor; } } - } } @@ -469,21 +481,21 @@ UnownedStringSlice getJSONTokenAsText(JSONTokenType type) { switch (type) { - case JSONTokenType::Invalid: return UnownedStringSlice::fromLiteral("invalid"); - case JSONTokenType::IntegerLiteral: return UnownedStringSlice::fromLiteral("integer literal"); - case JSONTokenType::FloatLiteral: return UnownedStringSlice::fromLiteral("float literal"); - case JSONTokenType::StringLiteral: return UnownedStringSlice::fromLiteral("string literal"); - case JSONTokenType::LBracket: return UnownedStringSlice::fromLiteral("["); - case JSONTokenType::RBracket: return UnownedStringSlice::fromLiteral("]"); - case JSONTokenType::LBrace: return UnownedStringSlice::fromLiteral("{"); - case JSONTokenType::RBrace: return UnownedStringSlice::fromLiteral("}"); - case JSONTokenType::Comma: return UnownedStringSlice::fromLiteral(","); - case JSONTokenType::Colon: return UnownedStringSlice::fromLiteral(":"); - case JSONTokenType::True: return UnownedStringSlice::fromLiteral("true"); - case JSONTokenType::False: return UnownedStringSlice::fromLiteral("false"); - case JSONTokenType::Null: return UnownedStringSlice::fromLiteral("null"); - case JSONTokenType::EndOfFile: return UnownedStringSlice::fromLiteral("end of file"); - default: break; + case JSONTokenType::Invalid: return UnownedStringSlice::fromLiteral("invalid"); + case JSONTokenType::IntegerLiteral: return UnownedStringSlice::fromLiteral("integer literal"); + case JSONTokenType::FloatLiteral: return UnownedStringSlice::fromLiteral("float literal"); + case JSONTokenType::StringLiteral: return UnownedStringSlice::fromLiteral("string literal"); + case JSONTokenType::LBracket: return UnownedStringSlice::fromLiteral("["); + case JSONTokenType::RBracket: return UnownedStringSlice::fromLiteral("]"); + case JSONTokenType::LBrace: return UnownedStringSlice::fromLiteral("{"); + case JSONTokenType::RBrace: return UnownedStringSlice::fromLiteral("}"); + case JSONTokenType::Comma: return UnownedStringSlice::fromLiteral(","); + case JSONTokenType::Colon: return UnownedStringSlice::fromLiteral(":"); + case JSONTokenType::True: return UnownedStringSlice::fromLiteral("true"); + case JSONTokenType::False: return UnownedStringSlice::fromLiteral("false"); + case JSONTokenType::Null: return UnownedStringSlice::fromLiteral("null"); + case JSONTokenType::EndOfFile: return UnownedStringSlice::fromLiteral("end of file"); + default: break; } SLANG_UNEXPECTED("JSONTokenType not known"); } diff --git a/source/compiler-core/slang-json-lexer.h b/source/compiler-core/slang-json-lexer.h index 6e4a42a32..cee97ae04 100644 --- a/source/compiler-core/slang-json-lexer.h +++ b/source/compiler-core/slang-json-lexer.h @@ -3,11 +3,11 @@ #define SLANG_JSON_LEXER_H #include "../core/slang-basic.h" - -#include "slang-source-loc.h" #include "slang-diagnostic-sink.h" +#include "slang-source-loc.h" -namespace Slang { +namespace Slang +{ enum class JSONTokenType { @@ -30,9 +30,9 @@ enum class JSONTokenType struct JSONToken { - JSONTokenType type; ///< The token type - SourceLoc loc; ///< Location in the source file - uint32_t length; ///< The length of the token in bytes + JSONTokenType type; ///< The token type + SourceLoc loc; ///< Location in the source file + uint32_t length; ///< The length of the token in bytes }; UnownedStringSlice getJSONTokenAsText(JSONTokenType type); @@ -40,33 +40,34 @@ UnownedStringSlice getJSONTokenAsText(JSONTokenType type); class JSONLexer { public: - /// Peek the current token + /// Peek the current token JSONToken& peekToken() { return m_token; } - /// Peek the current type + /// Peek the current type JSONTokenType peekType() { return m_token.type; } - /// Peek the current SourceLoc + /// Peek the current SourceLoc SourceLoc peekLoc() { return m_token.loc; } - /// Get the lexeme of JSONToken + /// Get the lexeme of JSONToken UnownedStringSlice getLexeme(const JSONToken& tok) const; - /// Peek the lexeme at the current position + /// Peek the lexeme at the current position UnownedStringSlice peekLexeme() const { return getLexeme(m_token); } - + JSONTokenType advance(); - /// Expects a token of type type. If found advances, if not returns an error and outputs to diagnostic sink + /// Expects a token of type type. If found advances, if not returns an error and outputs to + /// diagnostic sink SlangResult expect(JSONTokenType type); - /// Same as expect except out will hold the token. + /// Same as expect except out will hold the token. SlangResult expect(JSONTokenType type, JSONToken& out); - /// Returns true and advances if current token is type + /// Returns true and advances if current token is type bool advanceIf(JSONTokenType type); bool advanceIf(JSONTokenType type, JSONToken& out); - /// Must be called before use + /// Must be called before use SlangResult init(SourceView* sourceView, DiagnosticSink* sink); - /// Determines the first token from text. Useful for diagnostics on DiagnosticSink + /// Determines the first token from text. Useful for diagnostics on DiagnosticSink static UnownedStringSlice calcLexemeLocation(const UnownedStringSlice& text); protected: @@ -76,8 +77,11 @@ protected: const char* cursor; }; - /// Get the location of the cursor - SLANG_FORCE_INLINE SourceLoc _getLoc(const char* cursor) const { return m_startLoc + (cursor - m_contentStart); } + /// Get the location of the cursor + SLANG_FORCE_INLINE SourceLoc _getLoc(const char* cursor) const + { + return m_startLoc + (cursor - m_contentStart); + } const char* _lexLineComment(const char* cursor); const char* _lexBlockComment(const char* cursor); const char* _lexWhitespace(const char* cursor); diff --git a/source/compiler-core/slang-json-native.cpp b/source/compiler-core/slang-json-native.cpp index eb0f7d9ee..e4b425801 100644 --- a/source/compiler-core/slang-json-native.cpp +++ b/source/compiler-core/slang-json-native.cpp @@ -1,14 +1,13 @@ #include "slang-json-native.h" -#include "slang-com-helper.h" - #include "../core/slang-rtti-util.h" - +#include "slang-com-helper.h" #include "slang-json-diagnostics.h" -namespace Slang { +namespace Slang +{ -/* static */RttiTypeFuncsMap JSONNativeUtil::getTypeFuncsMap() +/* static */ RttiTypeFuncsMap JSONNativeUtil::getTypeFuncsMap() { RttiTypeFuncsMap typeMap; typeMap.add(GetRttiInfo::get(), GetRttiTypeFuncsForZeroPod::getFuncs()); @@ -17,7 +16,7 @@ namespace Slang { /* !!!!!!!!!!!!!!!!!!!!!!!!!!!! JSONToNativeConverter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */Index JSONToNativeConverter::_getFieldCount(const StructRttiInfo* structRttiInfo) +/* static */ Index JSONToNativeConverter::_getFieldCount(const StructRttiInfo* structRttiInfo) { if (structRttiInfo->m_super) { @@ -29,7 +28,9 @@ namespace Slang { } } -/* static */Index JSONToNativeConverter::_findFieldIndex(const StructRttiInfo* structRttiInfo, const UnownedStringSlice& fieldName) +/* static */ Index JSONToNativeConverter::_findFieldIndex( + const StructRttiInfo* structRttiInfo, + const UnownedStringSlice& fieldName) { if (structRttiInfo->m_super) { @@ -40,9 +41,13 @@ namespace Slang { } } - ConstArrayView fields(structRttiInfo->m_fields, structRttiInfo->m_fieldCount); + ConstArrayView fields( + structRttiInfo->m_fields, + structRttiInfo->m_fieldCount); - Index index = fields.findFirstIndex([fieldName](const StructRttiInfo::Field& field) ->bool { return fieldName == field.m_name; }); + Index index = fields.findFirstIndex( + [fieldName](const StructRttiInfo::Field& field) -> bool + { return fieldName == field.m_name; }); if (index >= 0 && structRttiInfo->m_super) { index += _getFieldCount(structRttiInfo->m_super); @@ -51,7 +56,11 @@ namespace Slang { return index; } -SlangResult JSONToNativeConverter::_structToNative(const ConstArrayView& pairs, const StructRttiInfo* structRttiInfo, void* out, Index& outFieldCount) +SlangResult JSONToNativeConverter::_structToNative( + const ConstArrayView& pairs, + const StructRttiInfo* structRttiInfo, + void* out, + Index& outFieldCount) { Index fieldCount = 0; @@ -77,14 +86,19 @@ SlangResult JSONToNativeConverter::_structToNative(const ConstArrayViewdiagnose(SourceLoc(), JSONDiagnostics::fieldRequiredOnType, field.m_name, structRttiInfo->m_name); + m_sink->diagnose( + SourceLoc(), + JSONDiagnostics::fieldRequiredOnType, + field.m_name, + structRttiInfo->m_name); // Unable to find this key return SLANG_FAIL; } // If there are any of the pairs, that are not in the type.. it's an error - const Index index = pairs.findFirstIndex([key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); + const Index index = pairs.findFirstIndex( + [key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); if (index < 0) { if (field.m_flags & StructRttiInfo::Flag::Optional) @@ -92,7 +106,11 @@ SlangResult JSONToNativeConverter::_structToNative(const ConstArrayViewdiagnose(SourceLoc(), JSONDiagnostics::fieldRequiredOnType, field.m_name, structRttiInfo->m_name); + m_sink->diagnose( + SourceLoc(), + JSONDiagnostics::fieldRequiredOnType, + field.m_name, + structRttiInfo->m_name); // Unable to find this key return SLANG_FAIL; @@ -107,7 +125,7 @@ SlangResult JSONToNativeConverter::_structToNative(const ConstArrayViewm_kind) { - case RttiInfo::Kind::Bool: + case RttiInfo::Kind::Bool: { *(bool*)out = m_container->asBool(in); return SLANG_OK; } - case RttiInfo::Kind::Struct: + case RttiInfo::Kind::Struct: { if (in.getKind() != JSONValue::Kind::Object) { @@ -150,38 +168,44 @@ SlangResult JSONToNativeConverter::convert(const JSONValue& in, const RttiInfo* for (auto& pair : pairs) { UnownedStringSlice fieldName = m_container->getStringFromKey(pair.key); - const Index index = _findFieldIndex(structRttiInfo, UnownedStringSlice(fieldName)); + const Index index = + _findFieldIndex(structRttiInfo, UnownedStringSlice(fieldName)); if (index < 0) { - m_sink->diagnose(pair.keyLoc, JSONDiagnostics::fieldNotDefinedOnType, fieldName, structRttiInfo->m_name); + m_sink->diagnose( + pair.keyLoc, + JSONDiagnostics::fieldNotDefinedOnType, + fieldName, + structRttiInfo->m_name); } } - // If these are different then there are fields defined in the object that are *not* defined in class definition + // If these are different then there are fields defined in the object that are *not* + // defined in class definition return SLANG_FAIL; } return SLANG_OK; } - case RttiInfo::Kind::Enum: + case RttiInfo::Kind::Enum: { return SLANG_E_NOT_IMPLEMENTED; } - case RttiInfo::Kind::String: + case RttiInfo::Kind::String: { *(String*)out = m_container->getTransientString(in); return SLANG_OK; } - case RttiInfo::Kind::UnownedStringSlice: + case RttiInfo::Kind::UnownedStringSlice: { - // Problem -> if the slice is a lexeme, then when we decode with getString, it will lose scope. - // So we do something a bit odd and place the decoding string + // Problem -> if the slice is a lexeme, then when we decode with getString, it will lose + // scope. So we do something a bit odd and place the decoding string *(UnownedStringSlice*)out = m_container->getString(in); return SLANG_OK; } - case RttiInfo::Kind::List: + case RttiInfo::Kind::List: { if (in.getKind() == JSONValue::Kind::Null) return SLANG_OK; @@ -200,7 +224,8 @@ SlangResult JSONToNativeConverter::convert(const JSONValue& in, const RttiInfo* const ListRttiInfo* listRttiInfo = static_cast(rttiInfo); auto elementType = listRttiInfo->m_elementType; - SLANG_RETURN_ON_FAIL(RttiUtil::setListCount(m_typeMap, elementType, out, arr.getCount())); + SLANG_RETURN_ON_FAIL( + RttiUtil::setListCount(m_typeMap, elementType, out, arr.getCount())); // Okay, we need to copy over one by one Byte* dstEles = list.getBuffer(); @@ -211,13 +236,14 @@ SlangResult JSONToNativeConverter::convert(const JSONValue& in, const RttiInfo* return SLANG_OK; } - case RttiInfo::Kind::FixedArray: + case RttiInfo::Kind::FixedArray: { if (in.getKind() != JSONValue::Kind::Array) { return SLANG_FAIL; } - const FixedArrayRttiInfo* fixedArrayRttiInfo = static_cast(rttiInfo); + const FixedArrayRttiInfo* fixedArrayRttiInfo = + static_cast(rttiInfo); const auto elementType = fixedArrayRttiInfo->m_elementType; const Index elementCount = Index(fixedArrayRttiInfo->m_elementCount); const auto elementSize = elementType->m_size; @@ -226,7 +252,11 @@ SlangResult JSONToNativeConverter::convert(const JSONValue& in, const RttiInfo* if (srcArray.getCount() > elementCount) { - m_sink->diagnose(in.loc, JSONDiagnostics::tooManyElementsForArray, srcArray.getCount(), elementCount); + m_sink->diagnose( + in.loc, + JSONDiagnostics::tooManyElementsForArray, + srcArray.getCount(), + elementCount); return SLANG_FAIL; } @@ -238,13 +268,13 @@ SlangResult JSONToNativeConverter::convert(const JSONValue& in, const RttiInfo* return SLANG_OK; } - case RttiInfo::Kind::Dictionary: + case RttiInfo::Kind::Dictionary: { - // We can *only* serialize this into a straight JSON object iff the key is a string-like type - // We could turn into (say) an array of keys and values + // We can *only* serialize this into a straight JSON object iff the key is a string-like + // type We could turn into (say) an array of keys and values break; } - case RttiInfo::Kind::Other: + case RttiInfo::Kind::Other: { if (rttiInfo == GetRttiInfo::get()) { @@ -255,16 +285,18 @@ SlangResult JSONToNativeConverter::convert(const JSONValue& in, const RttiInfo* } return SLANG_FAIL; } - default: break; + default: break; } return SLANG_FAIL; } -SlangResult JSONToNativeConverter::convertArrayToStruct(const JSONValue& value, const RttiInfo* rttiInfo, void* out) +SlangResult JSONToNativeConverter::convertArrayToStruct( + const JSONValue& value, + const RttiInfo* rttiInfo, + void* out) { // Check converting JSON array into a struct, as that's what this method supports - if (!(rttiInfo->m_kind == RttiInfo::Kind::Struct && - value.getKind() == JSONValue::Kind::Array)) + if (!(rttiInfo->m_kind == RttiInfo::Kind::Struct && value.getKind() == JSONValue::Kind::Array)) { // If they are the wrong types then just fail return SLANG_FAIL; @@ -274,7 +306,8 @@ SlangResult JSONToNativeConverter::convertArrayToStruct(const JSONValue& value, Index totalFieldCount = 0; ShortList infos; - for (const StructRttiInfo* cur = static_cast(rttiInfo); cur; cur = cur->m_super) + for (const StructRttiInfo* cur = static_cast(rttiInfo); cur; + cur = cur->m_super) { totalFieldCount += cur->m_fieldCount; infos.add(cur); @@ -300,7 +333,8 @@ SlangResult JSONToNativeConverter::convertArrayToStruct(const JSONValue& value, { // Convert the field const auto& field = info->m_fields[j]; - SLANG_RETURN_ON_FAIL(convert(array[argIndex++], field.m_type, dstBase + field.m_offset)); + SLANG_RETURN_ON_FAIL( + convert(array[argIndex++], field.m_type, dstBase + field.m_offset)); } } @@ -309,7 +343,10 @@ SlangResult JSONToNativeConverter::convertArrayToStruct(const JSONValue& value, /* !!!!!!!!!!!!!!!!!!!!!!!!!!!! NativeToJSONConverter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -SlangResult NativeToJSONConverter::_structToJSON(const StructRttiInfo* structRttiInfo, const void* src, List& outPairs) +SlangResult NativeToJSONConverter::_structToJSON( + const StructRttiInfo* structRttiInfo, + const void* src, + List& outPairs) { // Do the super class first if (structRttiInfo->m_super) @@ -326,7 +363,8 @@ SlangResult NativeToJSONConverter::_structToJSON(const StructRttiInfo* structRtt if (field.m_flags & StructRttiInfo::Flag::Optional) { - const RttiDefaultValue defaultValue = RttiDefaultValue(field.m_flags & uint8_t(RttiDefaultValue::Mask)); + const RttiDefaultValue defaultValue = + RttiDefaultValue(field.m_flags & uint8_t(RttiDefaultValue::Mask)); if (RttiUtil::isDefault(defaultValue, field.m_type, base + field.m_offset)) { // If it's a default, we don't bother writing it @@ -340,7 +378,11 @@ SlangResult NativeToJSONConverter::_structToJSON(const StructRttiInfo* structRtt if (SLANG_FAILED(res)) { - m_sink->diagnose(SourceLoc(), JSONDiagnostics::unableToConvertField, field.m_name, structRttiInfo->m_name); + m_sink->diagnose( + SourceLoc(), + JSONDiagnostics::unableToConvertField, + field.m_name, + structRttiInfo->m_name); return res; } @@ -366,25 +408,25 @@ SlangResult NativeToJSONConverter::convert(const RttiInfo* rttiInfo, const void* switch (rttiInfo->m_kind) { - case RttiInfo::Kind::Invalid: return SLANG_FAIL; - case RttiInfo::Kind::Bool: + case RttiInfo::Kind::Invalid: return SLANG_FAIL; + case RttiInfo::Kind::Bool: { out = JSONValue::makeBool(RttiUtil::asBool(rttiInfo, in)); return SLANG_OK; } - case RttiInfo::Kind::String: + case RttiInfo::Kind::String: { const String& str = *(const String*)in; out = m_container->createString(str.getUnownedSlice()); return SLANG_OK; } - case RttiInfo::Kind::UnownedStringSlice: + case RttiInfo::Kind::UnownedStringSlice: { const UnownedStringSlice& slice = *(const UnownedStringSlice*)in; out = m_container->createString(slice); return SLANG_OK; } - case RttiInfo::Kind::Struct: + case RttiInfo::Kind::Struct: { const StructRttiInfo* structRttiInfo = static_cast(rttiInfo); @@ -393,11 +435,11 @@ SlangResult NativeToJSONConverter::convert(const RttiInfo* rttiInfo, const void* out = m_container->createObject(pairs.getBuffer(), pairs.getCount()); return SLANG_OK; } - case RttiInfo::Kind::Enum: - { + case RttiInfo::Kind::Enum: + { return SLANG_E_NOT_IMPLEMENTED; } - case RttiInfo::Kind::List: + case RttiInfo::Kind::List: { const ListRttiInfo* listRttiInfo = static_cast(rttiInfo); const auto elementRttiInfo = listRttiInfo->m_elementType; @@ -422,9 +464,10 @@ SlangResult NativeToJSONConverter::convert(const RttiInfo* rttiInfo, const void* out = m_container->createArray(dstValues.getBuffer(), count); return SLANG_OK; } - case RttiInfo::Kind::FixedArray: + case RttiInfo::Kind::FixedArray: { - const FixedArrayRttiInfo* fixedArrayRttiInfo = static_cast(rttiInfo); + const FixedArrayRttiInfo* fixedArrayRttiInfo = + static_cast(rttiInfo); const auto elementType = fixedArrayRttiInfo->m_elementType; const auto elementCount = Index(fixedArrayRttiInfo->m_elementCount); const auto elementSize = elementType->m_size; @@ -441,21 +484,22 @@ SlangResult NativeToJSONConverter::convert(const RttiInfo* rttiInfo, const void* out = m_container->createArray(dstValues.getBuffer(), elementCount); return SLANG_OK; } - case RttiInfo::Kind::Dictionary: + case RttiInfo::Kind::Dictionary: { - const DictionaryRttiInfo* listRttiInfo = static_cast(rttiInfo); + const DictionaryRttiInfo* listRttiInfo = + static_cast(rttiInfo); const auto keyRttiInfo = listRttiInfo->m_keyType; const auto valueRttiInfo = listRttiInfo->m_valueType; SLANG_UNUSED(keyRttiInfo); SLANG_UNUSED(valueRttiInfo); - // We can *only* serialize this into a straight JSON object iff the key is a string-like type - // We could turn into (say) an array of keys and values + // We can *only* serialize this into a straight JSON object iff the key is a string-like + // type We could turn into (say) an array of keys and values break; } - case RttiInfo::Kind::Other: + case RttiInfo::Kind::Other: { if (rttiInfo == GetRttiInfo::get()) { @@ -468,13 +512,16 @@ SlangResult NativeToJSONConverter::convert(const RttiInfo* rttiInfo, const void* } break; } - default: break; + default: break; } return SLANG_E_NOT_IMPLEMENTED; } -SlangResult NativeToJSONConverter::convertStructToArray(const RttiInfo* rttiInfo, const void* in, JSONValue& out) +SlangResult NativeToJSONConverter::convertStructToArray( + const RttiInfo* rttiInfo, + const void* in, + JSONValue& out) { if (rttiInfo->m_kind != RttiInfo::Kind::Struct) { @@ -485,7 +532,8 @@ SlangResult NativeToJSONConverter::convertStructToArray(const RttiInfo* rttiInfo // Work out the total amount of fields, and all invloved struct types Index totalFieldsCount = 0; ShortList infos; - for (const StructRttiInfo* cur = static_cast(rttiInfo); cur; cur = cur->m_super) + for (const StructRttiInfo* cur = static_cast(rttiInfo); cur; + cur = cur->m_super) { totalFieldsCount += Index(cur->m_fieldCount); infos.add(cur); @@ -511,7 +559,8 @@ SlangResult NativeToJSONConverter::convertStructToArray(const RttiInfo* rttiInfo { const auto& field = structRttiInfo->m_fields[j]; // Convert the field - SLANG_RETURN_ON_FAIL(convert(field.m_type, argsBase + field.m_offset, argsArray[argsArrayIndex++])); + SLANG_RETURN_ON_FAIL( + convert(field.m_type, argsBase + field.m_offset, argsArray[argsArrayIndex++])); } } } diff --git a/source/compiler-core/slang-json-native.h b/source/compiler-core/slang-json-native.h index 6920d59e9..381d95fe0 100644 --- a/source/compiler-core/slang-json-native.h +++ b/source/compiler-core/slang-json-native.h @@ -1,35 +1,46 @@ #ifndef SLANG_COMPILER_CORE_JSON_NATIVE_H #define SLANG_COMPILER_CORE_JSON_NATIVE_H -#include "slang.h" #include "slang-com-helper.h" #include "slang-com-ptr.h" - #include "slang-json-value.h" +#include "slang.h" -namespace Slang { +namespace Slang +{ struct JSONToNativeConverter { SlangResult convert(const JSONValue& value, const RttiInfo* rttiInfo, void* out); - template - SlangResult convert(const JSONValue& value, T* in) { return convert(value, GetRttiInfo::get(), (void*)in); } - - template - SlangResult convertArrayToStruct(const JSONValue& value, T* in) { return convertArrayToStruct(value, GetRttiInfo::get(), (void*)in); } + template + SlangResult convert(const JSONValue& value, T* in) + { + return convert(value, GetRttiInfo::get(), (void*)in); + } + + template + SlangResult convertArrayToStruct(const JSONValue& value, T* in) + { + return convertArrayToStruct(value, GetRttiInfo::get(), (void*)in); + } SlangResult convertArrayToStruct(const JSONValue& value, const RttiInfo* rttiInfo, void* out); - JSONToNativeConverter(JSONContainer* container, RttiTypeFuncsMap* typeMap, DiagnosticSink* sink): - m_container(container), - m_typeMap(typeMap), - m_sink(sink) - {} + JSONToNativeConverter(JSONContainer* container, RttiTypeFuncsMap* typeMap, DiagnosticSink* sink) + : m_container(container), m_typeMap(typeMap), m_sink(sink) + { + } protected: static Index _getFieldCount(const StructRttiInfo* structRttiInfo); - static Index _findFieldIndex(const StructRttiInfo* structRttiInfo, const UnownedStringSlice& fieldName); + static Index _findFieldIndex( + const StructRttiInfo* structRttiInfo, + const UnownedStringSlice& fieldName); - SlangResult _structToNative(const ConstArrayView& pairs, const StructRttiInfo* structRttiInfo, void* out, Index& outFieldCount); + SlangResult _structToNative( + const ConstArrayView& pairs, + const StructRttiInfo* structRttiInfo, + void* out, + Index& outFieldCount); DiagnosticSink* m_sink; RttiTypeFuncsMap* m_typeMap; @@ -40,21 +51,29 @@ struct NativeToJSONConverter { SlangResult convert(const RttiInfo* rttiInfo, const void* in, JSONValue& out); - template - SlangResult convert(T* in, JSONValue& out) { return convert(GetRttiInfo::get(), (const void*)in, out); } + template + SlangResult convert(T* in, JSONValue& out) + { + return convert(GetRttiInfo::get(), (const void*)in, out); + } SlangResult convertStructToArray(const RttiInfo* rttiInfo, const void* in, JSONValue& out); - template - SlangResult convertStructToArray(T* in, JSONValue& out) { return convertStructToArray(GetRttiInfo::get(), (const void*)in, out); } + template + SlangResult convertStructToArray(T* in, JSONValue& out) + { + return convertStructToArray(GetRttiInfo::get(), (const void*)in, out); + } - NativeToJSONConverter(JSONContainer* container, RttiTypeFuncsMap* typeMap, DiagnosticSink* sink) : - m_container(container), - m_typeMap(typeMap), - m_sink(sink) - {} + NativeToJSONConverter(JSONContainer* container, RttiTypeFuncsMap* typeMap, DiagnosticSink* sink) + : m_container(container), m_typeMap(typeMap), m_sink(sink) + { + } protected: - SlangResult _structToJSON(const StructRttiInfo* structRttiInfo, const void* src, List& outPairs); + SlangResult _structToJSON( + const StructRttiInfo* structRttiInfo, + const void* src, + List& outPairs); DiagnosticSink* m_sink; RttiTypeFuncsMap* m_typeMap; diff --git a/source/compiler-core/slang-json-parser.cpp b/source/compiler-core/slang-json-parser.cpp index 52e46258a..c436468a4 100644 --- a/source/compiler-core/slang-json-parser.cpp +++ b/source/compiler-core/slang-json-parser.cpp @@ -1,15 +1,15 @@ // slang-json-parser.cpp #include "slang-json-parser.h" -#include "slang-json-diagnostics.h" - #include "../core/slang-string-escape-util.h" +#include "slang-json-diagnostics.h" /* https://www.json.org/json-en.html */ -namespace Slang { +namespace Slang +{ SlangResult JSONParser::_parseObject() { @@ -92,32 +92,35 @@ SlangResult JSONParser::_parseValue() { switch (m_lexer->peekType()) { - case JSONTokenType::True: - case JSONTokenType::False: - case JSONTokenType::Null: - case JSONTokenType::IntegerLiteral: - case JSONTokenType::FloatLiteral: - case JSONTokenType::StringLiteral: + case JSONTokenType::True: + case JSONTokenType::False: + case JSONTokenType::Null: + case JSONTokenType::IntegerLiteral: + case JSONTokenType::FloatLiteral: + case JSONTokenType::StringLiteral: { const JSONToken& tok = m_lexer->peekToken(); m_listener->addLexemeValue(tok.type, m_lexer->peekLexeme(), tok.loc); m_lexer->advance(); return SLANG_OK; } - case JSONTokenType::LBracket: + case JSONTokenType::LBracket: { return _parseArray(); } - case JSONTokenType::LBrace: + case JSONTokenType::LBrace: { return _parseObject(); } - default: + default: { - m_sink->diagnose(m_lexer->peekLoc(), JSONDiagnostics::unexpectedToken, getJSONTokenAsText(m_lexer->peekType())); + m_sink->diagnose( + m_lexer->peekLoc(), + JSONDiagnostics::unexpectedToken, + getJSONTokenAsText(m_lexer->peekType())); return SLANG_FAIL; } - case JSONTokenType::Invalid: + case JSONTokenType::Invalid: { // It's a lex error, so just fail return SLANG_FAIL; @@ -125,7 +128,11 @@ SlangResult JSONParser::_parseValue() } } -SlangResult JSONParser::parse(JSONLexer* lexer, SourceView* sourceView, JSONListener* listener, DiagnosticSink* sink) +SlangResult JSONParser::parse( + JSONLexer* lexer, + SourceView* sourceView, + JSONListener* listener, + DiagnosticSink* sink) { m_sourceView = sourceView; m_lexer = lexer; @@ -180,7 +187,8 @@ void JSONWriter::_nextLine() void JSONWriter::_maybeNextLine() { - // Nothing has been emitted, because nothing has been indented, and we must indent before an emit + // Nothing has been emitted, because nothing has been indented, and we must indent before an + // emit if (m_emittedIndent < 0) { } @@ -194,13 +202,13 @@ void JSONWriter::_handleFormat(Location loc) { switch (m_format) { - case IndentationStyle::Allman: + case IndentationStyle::Allman: { if (isComma(loc)) { _maybeNextLine(); } - else + else { if (isBefore(loc)) { @@ -221,7 +229,7 @@ void JSONWriter::_handleFormat(Location loc) } break; } - case IndentationStyle::KNR: + case IndentationStyle::KNR: { if (isComma(loc)) { @@ -231,7 +239,7 @@ void JSONWriter::_handleFormat(Location loc) _maybeNextLine(); } } - else + else { if (isBefore(loc)) { @@ -321,7 +329,7 @@ void JSONWriter::startArray(SourceLoc loc) _handleFormat(Location::BeforeOpenArray); _maybeEmitIndent(); - m_builder << "["; + m_builder << "["; _handleFormat(Location::AfterOpenArray); m_state.m_flags |= State::Flag::HasPrevious; @@ -352,7 +360,8 @@ void JSONWriter::endArray(SourceLoc loc) void JSONWriter::addUnquotedKey(const UnownedStringSlice& key, SourceLoc loc) { SLANG_UNUSED(loc); - SLANG_ASSERT(m_state.m_kind == State::Kind::Object && (m_state.m_flags & State::Flag::HasKey) == 0); + SLANG_ASSERT( + m_state.m_kind == State::Kind::Object && (m_state.m_flags & State::Flag::HasKey) == 0); _maybeEmitFieldComma(); _maybeEmitIndent(); @@ -371,7 +380,8 @@ void JSONWriter::addUnquotedKey(const UnownedStringSlice& key, SourceLoc loc) void JSONWriter::addQuotedKey(const UnownedStringSlice& key, SourceLoc loc) { SLANG_UNUSED(loc); - SLANG_ASSERT(m_state.m_kind == State::Kind::Object && (m_state.m_flags & State::Flag::HasKey) == 0); + SLANG_ASSERT( + m_state.m_kind == State::Kind::Object && (m_state.m_flags & State::Flag::HasKey) == 0); // It should be quoted SLANG_ASSERT(key.getLength() >= 2 && key[0] == '"' && key[key.getLength() - 1] == '"'); @@ -412,29 +422,29 @@ void JSONWriter::addLexemeValue(JSONTokenType type, const UnownedStringSlice& va switch (type) { - case JSONTokenType::IntegerLiteral: - case JSONTokenType::FloatLiteral: - case JSONTokenType::StringLiteral: + case JSONTokenType::IntegerLiteral: + case JSONTokenType::FloatLiteral: + case JSONTokenType::StringLiteral: { m_builder << value; break; } - case JSONTokenType::True: + case JSONTokenType::True: { m_builder << UnownedStringSlice::fromLiteral("true"); break; } - case JSONTokenType::False: + case JSONTokenType::False: { m_builder << UnownedStringSlice::fromLiteral("false"); break; } - case JSONTokenType::Null: + case JSONTokenType::Null: { m_builder << UnownedStringSlice::fromLiteral("null"); break; } - default: + default: { SLANG_ASSERT(!"Can only emit values"); } @@ -460,7 +470,8 @@ void JSONWriter::addFloatValue(double value, SourceLoc loc) void JSONWriter::addBoolValue(bool inValue, SourceLoc loc) { _preValue(loc); - const UnownedStringSlice slice = inValue ? UnownedStringSlice::fromLiteral("true") : UnownedStringSlice::fromLiteral("false"); + const UnownedStringSlice slice = inValue ? UnownedStringSlice::fromLiteral("true") + : UnownedStringSlice::fromLiteral("false"); m_builder << slice; _postValue(); } diff --git a/source/compiler-core/slang-json-parser.h b/source/compiler-core/slang-json-parser.h index 2391ea0d2..d226e7fb9 100644 --- a/source/compiler-core/slang-json-parser.h +++ b/source/compiler-core/slang-json-parser.h @@ -5,54 +5,58 @@ #include "slang-json-lexer.h" -namespace Slang { +namespace Slang +{ class JSONListener { public: - /// Start an object + /// Start an object virtual void startObject(SourceLoc loc) = 0; - /// End an object + /// End an object virtual void endObject(SourceLoc loc) = 0; - /// Start an array + /// Start an array virtual void startArray(SourceLoc loc) = 0; - /// End and array + /// End and array virtual void endArray(SourceLoc loc) = 0; - /// Add the key. Must be followed by addXXXValue. + /// Add the key. Must be followed by addXXXValue. virtual void addQuotedKey(const UnownedStringSlice& key, SourceLoc loc) = 0; virtual void addUnquotedKey(const UnownedStringSlice& key, SourceLoc loc) = 0; - /// Can be performed in an array or after an addLexemeKey in an object - virtual void addLexemeValue(JSONTokenType type, const UnownedStringSlice& value, SourceLoc loc) = 0; + /// Can be performed in an array or after an addLexemeKey in an object + virtual void addLexemeValue( + JSONTokenType type, + const UnownedStringSlice& value, + SourceLoc loc) = 0; - /// An integer value + /// An integer value virtual void addIntegerValue(int64_t value, SourceLoc loc) = 0; - /// Add a floating point value + /// Add a floating point value virtual void addFloatValue(double value, SourceLoc loc) = 0; - /// Add a boolean value + /// Add a boolean value virtual void addBoolValue(bool value, SourceLoc loc) = 0; - /// Add a string value. NOTE! string is unescaped/quoted + /// Add a string value. NOTE! string is unescaped/quoted virtual void addStringValue(const UnownedStringSlice& string, SourceLoc loc) = 0; - /// Add a null value + /// Add a null value virtual void addNullValue(SourceLoc loc) = 0; }; class JSONWriter : public JSONListener { public: - /* + /* https://en.wikipedia.org/wiki/Indentation_style */ enum class IndentationStyle { - Allman, ///< After every value, and opening, closing all other types - KNR, ///< K&R like. Fields have CR. + Allman, ///< After every value, and opening, closing all other types + KNR, ///< K&R like. Fields have CR. }; - enum class LocationType : uint8_t + enum class LocationType : uint8_t { Object, Array, @@ -78,11 +82,22 @@ public: CountOf, }; - static LocationType getLocationType(Location loc) { return isObject(loc) ? LocationType::Object : (isComma(loc) ? LocationType::Comma : LocationType::Array); } + static LocationType getLocationType(Location loc) + { + return isObject(loc) ? LocationType::Object + : (isComma(loc) ? LocationType::Comma : LocationType::Array); + } - static bool isObjectLike(Location loc) { return Index(loc) <= Index(Location::AfterCloseArray); } + static bool isObjectLike(Location loc) + { + return Index(loc) <= Index(Location::AfterCloseArray); + } static bool isObject(Location loc) { return Index(loc) <= Index(Location::AfterCloseObject); } - static bool isArray(Location loc) { return Index(loc) >= Index(Location::BeforeOpenArray) && Index(loc) <= Index(Location::AfterCloseArray); } + static bool isArray(Location loc) + { + return Index(loc) >= Index(Location::BeforeOpenArray) && + Index(loc) <= Index(Location::AfterCloseArray); + } static bool isComma(Location loc) { return Index(loc) >= Index(Location::FieldComma); } static bool isOpen(Location loc) { return isObjectLike(loc) && (Index(loc) & 1) == 0; } static bool isClose(Location loc) { return isObjectLike(loc) && (Index(loc) & 1) != 0; } @@ -96,14 +111,15 @@ public: virtual void endArray(SourceLoc loc) SLANG_OVERRIDE; virtual void addQuotedKey(const UnownedStringSlice& key, SourceLoc loc) SLANG_OVERRIDE; virtual void addUnquotedKey(const UnownedStringSlice& key, SourceLoc loc) SLANG_OVERRIDE; - virtual void addLexemeValue(JSONTokenType type, const UnownedStringSlice& value, SourceLoc loc) SLANG_OVERRIDE; + virtual void addLexemeValue(JSONTokenType type, const UnownedStringSlice& value, SourceLoc loc) + SLANG_OVERRIDE; virtual void addIntegerValue(int64_t value, SourceLoc loc) SLANG_OVERRIDE; virtual void addFloatValue(double value, SourceLoc loc) SLANG_OVERRIDE; virtual void addBoolValue(bool value, SourceLoc loc) SLANG_OVERRIDE; virtual void addStringValue(const UnownedStringSlice& string, SourceLoc loc) SLANG_OVERRIDE; virtual void addNullValue(SourceLoc loc) SLANG_OVERRIDE; - /// Get the builder + /// Get the builder StringBuilder& getBuilder() { return m_builder; } JSONWriter(IndentationStyle format, Index lineLengthLimit = -1) @@ -131,7 +147,7 @@ protected: enum Enum : Flags { HasPrevious = 0x01, - HasKey = 0x02, + HasKey = 0x02, }; }; @@ -139,10 +155,10 @@ protected: { switch (m_kind) { - case Kind::Root: return (m_flags & Flag::HasPrevious) == 0; - case Kind::Array: return true; - case Kind::Object: return (m_flags & Flag::HasKey) != 0; - default: return false; + case Kind::Root: return (m_flags & Flag::HasPrevious) == 0; + case Kind::Array: return true; + case Kind::Object: return (m_flags & Flag::HasKey) != 0; + default: return false; } } @@ -156,7 +172,7 @@ protected: Index _getLineLengthAfterIndent(); - /// Only emits the indent if at start of line + /// Only emits the indent if at start of line void _maybeEmitIndent(); void _emitIndent(); @@ -167,20 +183,24 @@ protected: void _postValue(); void _indent() { m_currentIndent++; } - void _dedent() { --m_currentIndent; SLANG_ASSERT(m_currentIndent >= 0); } + void _dedent() + { + --m_currentIndent; + SLANG_ASSERT(m_currentIndent >= 0); + } - /// True if the line is indented at the required level + /// True if the line is indented at the required level bool _hasIndent() { return m_emittedIndent >= 0 && m_emittedIndent == m_currentIndent; } - + Index m_currentIndent = 0; char m_indentChar = ' '; Index m_indentCharCount = 4; Index m_lineIndex = 0; Index m_lineStart = 0; - Index m_emittedIndent = -1; /// If -1 for current line there is no indent emitted + Index m_emittedIndent = -1; /// If -1 for current line there is no indent emitted - Index m_lineLengthLimit = -1; /// The limit is only applied *AFTER* indentation + Index m_lineLengthLimit = -1; /// The limit is only applied *AFTER* indentation IndentationStyle m_format; @@ -192,7 +212,11 @@ protected: class JSONParser { public: - SlangResult parse(JSONLexer* lexer, SourceView* sourceView, JSONListener* listener, DiagnosticSink* sink); + SlangResult parse( + JSONLexer* lexer, + SourceView* sourceView, + JSONListener* listener, + DiagnosticSink* sink); protected: SlangResult _parseValue(); @@ -206,7 +230,6 @@ protected: }; - } // namespace Slang #endif diff --git a/source/compiler-core/slang-json-rpc-connection.cpp b/source/compiler-core/slang-json-rpc-connection.cpp index af9dd9e48..79ffc9583 100644 --- a/source/compiler-core/slang-json-rpc-connection.cpp +++ b/source/compiler-core/slang-json-rpc-connection.cpp @@ -1,23 +1,25 @@ // slang-json-rpc-connection.cpp #include "slang-json-rpc-connection.h" -#include "../core/slang-string-util.h" #include "../core/slang-process-util.h" #include "../core/slang-short-list.h" - -#include "slang-json-rpc.h" +#include "../core/slang-string-util.h" #include "slang-json-native.h" +#include "slang-json-rpc.h" -namespace Slang { +namespace Slang +{ /// Ctor -JSONRPCConnection::JSONRPCConnection(): - m_container(nullptr), - m_typeMap(JSONNativeUtil::getTypeFuncsMap()) +JSONRPCConnection::JSONRPCConnection() + : m_container(nullptr), m_typeMap(JSONNativeUtil::getTypeFuncsMap()) { } -SlangResult JSONRPCConnection::init(HTTPPacketConnection* connection, CallStyle defaultCallStyle, Process* process) +SlangResult JSONRPCConnection::init( + HTTPPacketConnection* connection, + CallStyle defaultCallStyle, + Process* process) { m_connection = connection; m_process = process; @@ -25,11 +27,12 @@ SlangResult JSONRPCConnection::init(HTTPPacketConnection* connection, CallStyle { // If a call style isn't set, use the prefered style const CallStyle preferedCallStyle = CallStyle::Array; - defaultCallStyle = (defaultCallStyle == CallStyle::Default) ? preferedCallStyle : defaultCallStyle; + defaultCallStyle = + (defaultCallStyle == CallStyle::Default) ? preferedCallStyle : defaultCallStyle; m_defaultCallStyle = defaultCallStyle; } - - + + m_sourceManager.initialize(nullptr, nullptr); m_diagnosticSink.init(&m_sourceManager, &JSONLexer::calcLexemeLocation); m_container.setSourceManager(&m_sourceManager); @@ -77,7 +80,7 @@ void JSONRPCConnection::disconnect() { if (m_connection) { - // Send. If succeeded, wait + // Send. If succeeded, wait if (SLANG_SUCCEEDED(sendCall(UnownedStringSlice::fromLiteral("quit")))) { // Wait for termination @@ -126,7 +129,10 @@ SlangResult JSONRPCConnection::sendError(JSONRPC::ErrorCode code, const JSONValu return sendError(code, m_diagnosticSink.outputBuffer.getUnownedSlice(), id); } -SlangResult JSONRPCConnection::sendError(JSONRPC::ErrorCode errorCode, const UnownedStringSlice& msg, const JSONValue& id) +SlangResult JSONRPCConnection::sendError( + JSONRPC::ErrorCode errorCode, + const UnownedStringSlice& msg, + const JSONValue& id) { JSONRPCErrorResponse errorResponse; errorResponse.error.code = Int(errorCode); @@ -136,25 +142,33 @@ SlangResult JSONRPCConnection::sendError(JSONRPC::ErrorCode errorCode, const Uno return sendRPC(&errorResponse); } -SlangResult JSONRPCConnection::checkArrayObjectWrap( const JSONValue& srcArgs, const RttiInfo* dstArgsRttiInfo, void* dstArgs, const JSONValue& id ) +SlangResult JSONRPCConnection::checkArrayObjectWrap( + const JSONValue& srcArgs, + const RttiInfo* dstArgsRttiInfo, + void* dstArgs, + const JSONValue& id) { - if ( dstArgsRttiInfo->m_kind == RttiInfo::Kind::Struct && - srcArgs.getKind() == JSONValue::Kind::Array ) + if (dstArgsRttiInfo->m_kind == RttiInfo::Kind::Struct && + srcArgs.getKind() == JSONValue::Kind::Array) { - auto array = m_container.getArray( srcArgs ); - if ( array.getCount() == 1 ) + auto array = m_container.getArray(srcArgs); + if (array.getCount() == 1) { - return toNativeOrSendError( array[0], dstArgsRttiInfo, dstArgs, id ); + return toNativeOrSendError(array[0], dstArgsRttiInfo, dstArgs, id); } return SLANG_OK; } else { - return toNativeOrSendError( srcArgs, dstArgsRttiInfo, dstArgs, id ); + return toNativeOrSendError(srcArgs, dstArgsRttiInfo, dstArgs, id); } } -SlangResult JSONRPCConnection::toNativeArgsOrSendError(const JSONValue& srcArgs, const RttiInfo* dstArgsRttiInfo, void* dstArgs, const JSONValue& id) +SlangResult JSONRPCConnection::toNativeArgsOrSendError( + const JSONValue& srcArgs, + const RttiInfo* dstArgsRttiInfo, + void* dstArgs, + const JSONValue& id) { if (dstArgsRttiInfo->m_kind == RttiInfo::Kind::Struct && srcArgs.getKind() == JSONValue::Kind::Array) @@ -172,12 +186,16 @@ SlangResult JSONRPCConnection::toNativeArgsOrSendError(const JSONValue& srcArgs, } } -SlangResult JSONRPCConnection::toNativeOrSendError(const JSONValue& value, const RttiInfo* info, void* dst, const JSONValue& id) +SlangResult JSONRPCConnection::toNativeOrSendError( + const JSONValue& value, + const RttiInfo* info, + void* dst, + const JSONValue& id) { m_diagnosticSink.outputBuffer.clear(); JSONToNativeConverter converter(&m_container, &m_typeMap, &m_diagnosticSink); - + if (SLANG_FAILED(converter.convert(value, info, dst))) { return sendError(JSONRPC::ErrorCode::InvalidRequest, id); @@ -196,7 +214,10 @@ SlangResult JSONRPCConnection::sendCall(const UnownedStringSlice& method, const return SLANG_OK; } -SlangResult JSONRPCConnection::sendResult(const RttiInfo* rttiInfo, const void* result, const JSONValue& id) +SlangResult JSONRPCConnection::sendResult( + const RttiInfo* rttiInfo, + const void* result, + const JSONValue& id) { JSONResultResponse response; response.id = id; @@ -209,12 +230,21 @@ SlangResult JSONRPCConnection::sendResult(const RttiInfo* rttiInfo, const void* return SLANG_OK; } -SlangResult JSONRPCConnection::sendCall(const UnownedStringSlice& method, const RttiInfo* argsRttiInfo, const void* args, const JSONValue& id) +SlangResult JSONRPCConnection::sendCall( + const UnownedStringSlice& method, + const RttiInfo* argsRttiInfo, + const void* args, + const JSONValue& id) { return sendCall(m_defaultCallStyle, method, argsRttiInfo, args, id); } -SlangResult JSONRPCConnection::sendCall(CallStyle callStyle, const UnownedStringSlice& method, const RttiInfo* argsRttiInfo, const void* args, const JSONValue& id) +SlangResult JSONRPCConnection::sendCall( + CallStyle callStyle, + const UnownedStringSlice& method, + const RttiInfo* argsRttiInfo, + const void* args, + const JSONValue& id) { JSONRPCCall call; call.id = id; @@ -222,7 +252,7 @@ SlangResult JSONRPCConnection::sendCall(CallStyle callStyle, const UnownedString // Set up the converter to now convert the args. NativeToJSONConverter converter(&m_container, &m_typeMap, &m_diagnosticSink); - + // If we have a struct *and* call style is 'array', do special handling if (argsRttiInfo->m_kind == RttiInfo::Kind::Struct && _getCallStyle(callStyle) == CallStyle::Array) @@ -235,7 +265,7 @@ SlangResult JSONRPCConnection::sendCall(CallStyle callStyle, const UnownedString // Convert the args/params in the 'object' sytle SLANG_RETURN_ON_FAIL(converter.convert(argsRttiInfo, args, call.params)); } - + // Send the RPC SLANG_RETURN_ON_FAIL(sendRPC(&call)); return SLANG_OK; @@ -263,7 +293,8 @@ SlangResult JSONRPCConnection::tryReadMessage() clearBuffers(); { - const SlangResult res = JSONRPCUtil::parseJSON(slice, &m_container, &m_diagnosticSink, m_jsonRoot); + const SlangResult res = + JSONRPCUtil::parseJSON(slice, &m_container, &m_diagnosticSink, m_jsonRoot); // Consume that content/packet m_connection->consumeContent(); @@ -346,4 +377,4 @@ SlangResult JSONRPCConnection::getRPCOrSendError(const RttiInfo* rttiInfo, void* return res; } -} // namespcae Slang +} // namespace Slang diff --git a/source/compiler-core/slang-json-rpc-connection.h b/source/compiler-core/slang-json-rpc-connection.h index f5525d033..5ee963ec8 100644 --- a/source/compiler-core/slang-json-rpc-connection.h +++ b/source/compiler-core/slang-json-rpc-connection.h @@ -3,17 +3,15 @@ #include "../../source/core/slang-http.h" #include "../../source/core/slang-process.h" - #include "slang-diagnostic-sink.h" -#include "slang-source-loc.h" -#include "slang-json-value.h" -#include "slang-json-rpc.h" - #include "slang-json-diagnostics.h" - +#include "slang-json-rpc.h" +#include "slang-json-value.h" +#include "slang-source-loc.h" #include "slang-test-server-protocol.h" -namespace Slang { +namespace Slang +{ /* A type to handle communication via the JSON-RPC protocol. @@ -23,164 +21,245 @@ use the JSON-RPC protocol types. These types will hold items that can vary (like in JSONValue parameters. Code can use regular JSON functions to access/process. Doing conversions to native types and JSON manually can be a fairly monotonous task. To avoid this -effort Rtti and JSON<->Rtti conversions can be used. For example sendCall will send a JSON-RPC 'call' method, -with the parameters being converted from some native type. For this to work the type T must be determinable -via GetRttiType, and T must only contain types that JSON<->Rtti conversion supports. +effort Rtti and JSON<->Rtti conversions can be used. For example sendCall will send a JSON-RPC +'call' method, with the parameters being converted from some native type. For this to work the type +T must be determinable via GetRttiType, and T must only contain types that JSON<->Rtti conversion +supports. */ class JSONRPCConnection : public RefObject { public: - enum class CallStyle { - Default, ///< The default - Object, ///< Params are passed as an object - Array, ///< Params are passed as an array + Default, ///< The default + Object, ///< Params are passed as an object + Array, ///< Params are passed as an array }; - /// An init function must be called before use - /// If a process is implementing the server it should be passed in if the process needs to shut down if the connection does - SlangResult init(HTTPPacketConnection* connection, CallStyle callStyle = CallStyle::Default, Process* process = nullptr); + /// An init function must be called before use + /// If a process is implementing the server it should be passed in if the process needs to shut + /// down if the connection does + SlangResult init( + HTTPPacketConnection* connection, + CallStyle callStyle = CallStyle::Default, + Process* process = nullptr); - /// Initialize using stdin/out streams for input/output. - SlangResult initWithStdStreams(CallStyle callStyle = CallStyle::Default, Process* process = nullptr); + /// Initialize using stdin/out streams for input/output. + SlangResult initWithStdStreams( + CallStyle callStyle = CallStyle::Default, + Process* process = nullptr); - /// Disconnect. May block while server shuts down + /// Disconnect. May block while server shuts down void disconnect(); - SlangResult checkArrayObjectWrap( const JSONValue& srcArgs, const RttiInfo* dstArgsRttiInfo, void* dstArgs, const JSONValue& id ); - - /// Convert value to dst. Will write response on fails - SlangResult toNativeOrSendError(const JSONValue& value, const RttiInfo* info, void* dst, const JSONValue& id); - - template - SlangResult toNativeOrSendError(const JSONValue& value, T* data, const JSONValue& id) { return toNativeOrSendError(value, GetRttiInfo::get(), data, id); } - - /// Convert value to dst. - /// The 'Args' aspect here is to handle Args/Params in JSON-RPC which can be specified as an array or object style. - /// This call will automatically handle either case. - /// toNativeOrSendError does not assume the thing being converted is args, and so doesn't allow such a transformation. - /// Will write error response on failure. - SlangResult toNativeArgsOrSendError(const JSONValue& srcArgs, const RttiInfo* dstArgsRttiInfo, void* dstArgs, const JSONValue& id); + SlangResult checkArrayObjectWrap( + const JSONValue& srcArgs, + const RttiInfo* dstArgsRttiInfo, + void* dstArgs, + const JSONValue& id); + + /// Convert value to dst. Will write response on fails + SlangResult toNativeOrSendError( + const JSONValue& value, + const RttiInfo* info, + void* dst, + const JSONValue& id); + + template + SlangResult toNativeOrSendError(const JSONValue& value, T* data, const JSONValue& id) + { + return toNativeOrSendError(value, GetRttiInfo::get(), data, id); + } - template - SlangResult toNativeArgsOrSendError(const JSONValue& srcArgs, T* dstArgs, const JSONValue& id) { return toNativeArgsOrSendError(srcArgs, GetRttiInfo::get(), dstArgs, id); } + /// Convert value to dst. + /// The 'Args' aspect here is to handle Args/Params in JSON-RPC which can be specified as an + /// array or object style. This call will automatically handle either case. toNativeOrSendError + /// does not assume the thing being converted is args, and so doesn't allow such a + /// transformation. Will write error response on failure. + SlangResult toNativeArgsOrSendError( + const JSONValue& srcArgs, + const RttiInfo* dstArgsRttiInfo, + void* dstArgs, + const JSONValue& id); + + template + SlangResult toNativeArgsOrSendError(const JSONValue& srcArgs, T* dstArgs, const JSONValue& id) + { + return toNativeArgsOrSendError(srcArgs, GetRttiInfo::get(), dstArgs, id); + } - template + template SlangResult toValidNativeOrSendError(const JSONValue& value, T* data, const JSONValue& id); - /// Send a RPC response (ie should only be one of the JSONRPC classes) + /// Send a RPC response (ie should only be one of the JSONRPC classes) SlangResult sendRPC(const RttiInfo* info, const void* data); - template - SlangResult sendRPC(const T* data) { return sendRPC(GetRttiInfo::get(), (const void*)data); } + template + SlangResult sendRPC(const T* data) + { + return sendRPC(GetRttiInfo::get(), (const void*)data); + } - /// Send an error + /// Send an error SlangResult sendError(JSONRPC::ErrorCode code, const JSONValue& id); - SlangResult sendError(JSONRPC::ErrorCode errorCode, const UnownedStringSlice& msg, const JSONValue& id); - - /// Send a 'call' - /// Uses the default CallStyle as set when init - SlangResult sendCall(const UnownedStringSlice& method, const RttiInfo* argsRttiInfo, const void* args, const JSONValue& id = JSONValue()); - template - SlangResult sendCall(const UnownedStringSlice& method, const T* args, const JSONValue& id = JSONValue()) { return sendCall(method, GetRttiInfo::get(), (const void*)args, id); } + SlangResult sendError( + JSONRPC::ErrorCode errorCode, + const UnownedStringSlice& msg, + const JSONValue& id); + + /// Send a 'call' + /// Uses the default CallStyle as set when init + SlangResult sendCall( + const UnownedStringSlice& method, + const RttiInfo* argsRttiInfo, + const void* args, + const JSONValue& id = JSONValue()); + template + SlangResult sendCall( + const UnownedStringSlice& method, + const T* args, + const JSONValue& id = JSONValue()) + { + return sendCall(method, GetRttiInfo::get(), (const void*)args, id); + } - /// Send a 'call' - /// Uses the call mechanism specified in callStyle. It is valid to pass as Default. - SlangResult sendCall(CallStyle callStyle, const UnownedStringSlice& method, const RttiInfo* argsRttiInfo, const void* args, const JSONValue& id = JSONValue()); - template - SlangResult sendCall(CallStyle callStyle, const UnownedStringSlice& method, const T* args, const JSONValue& id = JSONValue()) { return sendCall(callStyle, method, GetRttiInfo::get(), (const void*)args, id); } + /// Send a 'call' + /// Uses the call mechanism specified in callStyle. It is valid to pass as Default. + SlangResult sendCall( + CallStyle callStyle, + const UnownedStringSlice& method, + const RttiInfo* argsRttiInfo, + const void* args, + const JSONValue& id = JSONValue()); + template + SlangResult sendCall( + CallStyle callStyle, + const UnownedStringSlice& method, + const T* args, + const JSONValue& id = JSONValue()) + { + return sendCall(callStyle, method, GetRttiInfo::get(), (const void*)args, id); + } - /// Send a call, wheret there are no arguments + /// Send a call, wheret there are no arguments SlangResult sendCall(const UnownedStringSlice& method, const JSONValue& id = JSONValue()); - template - SlangResult sendResult(const T* result, const JSONValue& id) { return sendResult(GetRttiInfo::get(), (const void*)result, id); } + template + SlangResult sendResult(const T* result, const JSONValue& id) + { + return sendResult(GetRttiInfo::get(), (const void*)result, id); + } SlangResult sendResult(const RttiInfo* rttiInfo, const void* result, const JSONValue& id); - /// Try to read a message. Will return if message is not available. + /// Try to read a message. Will return if message is not available. SlangResult tryReadMessage(); - /// Will block for message/result up to time + /// Will block for message/result up to time SlangResult waitForResult(Int timeOutInMs = -1); - /// If we have an JSON-RPC message m_jsonRoot the root. + /// If we have an JSON-RPC message m_jsonRoot the root. bool hasMessage() const { return m_jsonRoot.isValid(); } - /// If there is a message returns kind of JSON RPC message + /// If there is a message returns kind of JSON RPC message JSONRPCMessageType getMessageType(); - /// Get JSON-RPC message (ie one of JSONRPC classes) - template - SlangResult getRPC(T* out) { return getRPC(GetRttiInfo::get(), (void*)out); } + /// Get JSON-RPC message (ie one of JSONRPC classes) + template + SlangResult getRPC(T* out) + { + return getRPC(GetRttiInfo::get(), (void*)out); + } SlangResult getRPC(const RttiInfo* rttiInfo, void* out); - /// Get JSON-RPC message (ie one of JSONRPC prefixed classes) - /// If there is a message and there is a failure, will send an error response - template - SlangResult getRPCOrSendError(T* out) { return getRPCOrSendError(GetRttiInfo::get(), (void*)out); } + /// Get JSON-RPC message (ie one of JSONRPC prefixed classes) + /// If there is a message and there is a failure, will send an error response + template + SlangResult getRPCOrSendError(T* out) + { + return getRPCOrSendError(GetRttiInfo::get(), (void*)out); + } SlangResult getRPCOrSendError(const RttiInfo* rttiInfo, void* out); - /// Get message (has to be part of JSONRPCResultResponse) - template - SlangResult getMessage(T* out) { return getMessage(GetRttiInfo::get(), (void*)out); } + /// Get message (has to be part of JSONRPCResultResponse) + template + SlangResult getMessage(T* out) + { + return getMessage(GetRttiInfo::get(), (void*)out); + } SlangResult getMessage(const RttiInfo* rttiInfo, void* out); - /// If there is a message and there is a failure, will send an error response - template - SlangResult getMessageOrSendError(T* out) { return getMessageOrSendError(GetRttiInfo::get(), (void*)out); } + /// If there is a message and there is a failure, will send an error response + template + SlangResult getMessageOrSendError(T* out) + { + return getMessageOrSendError(GetRttiInfo::get(), (void*)out); + } SlangResult getMessageOrSendError(const RttiInfo* rttiInfo, void* out); - /// Clears all the internal buffers (for JSON/Source/etc). - /// Happens automatically on tryReadMessage/readMessage + /// Clears all the internal buffers (for JSON/Source/etc). + /// Happens automatically on tryReadMessage/readMessage void clearBuffers(); - /// True if this connection is active + /// True if this connection is active bool isActive(); - /// Get the id of the current message + /// Get the id of the current message JSONValue getCurrentMessageId(); - /// Get the diagnostic sink. Can queue up errors before sending an error - DiagnosticSink* getSink() { return &m_diagnosticSink; } + /// Get the diagnostic sink. Can queue up errors before sending an error + DiagnosticSink* getSink() { return &m_diagnosticSink; } - /// Get the container - JSONContainer* getContainer() { return &m_container; } + /// Get the container + JSONContainer* getContainer() { return &m_container; } - /// Turn a value into a persistant value. This will also remove any sourceLoc under the assumption that it's highly likely - /// it will become invalid in most usage scenarios. - PersistentJSONValue getPersistentValue(const JSONValue& value) { return PersistentJSONValue(value, &m_container, SourceLoc()); } + /// Turn a value into a persistant value. This will also remove any sourceLoc under the + /// assumption that it's highly likely it will become invalid in most usage scenarios. + PersistentJSONValue getPersistentValue(const JSONValue& value) + { + return PersistentJSONValue(value, &m_container, SourceLoc()); + } HTTPPacketConnection* getUnderlyingConnection() { return m_connection.Ptr(); } - /// Dtor + /// Dtor ~JSONRPCConnection() { disconnect(); } - /// Ctor + /// Ctor JSONRPCConnection(); protected: - CallStyle _getCallStyle(CallStyle callStyle) const { return (callStyle == CallStyle::Default) ? m_defaultCallStyle : callStyle; } + CallStyle _getCallStyle(CallStyle callStyle) const + { + return (callStyle == CallStyle::Default) ? m_defaultCallStyle : callStyle; + } - RefPtr m_process; ///< Backing process (optional) - RefPtr m_connection; ///< The underlying 'transport' connection, whilst HTTP currently doesn't have to be + RefPtr m_process; ///< Backing process (optional) + RefPtr m_connection; ///< The underlying 'transport' connection, whilst + ///< HTTP currently doesn't have to be - DiagnosticSink m_diagnosticSink; ///< Holds any diagnostics typically generated by parsing JSON, producing JSON from native types + DiagnosticSink m_diagnosticSink; ///< Holds any diagnostics typically generated by parsing JSON, + ///< producing JSON from native types - SourceManager m_sourceManager; ///< Holds the JSON text for current message/output. Is cleared regularly. - JSONContainer m_container; ///< Holds the backing memory for jsonMemory, and used when converting input into output JSON + SourceManager + m_sourceManager; ///< Holds the JSON text for current message/output. Is cleared regularly. + JSONContainer m_container; ///< Holds the backing memory for jsonMemory, and used when + ///< converting input into output JSON - JSONValue m_jsonRoot; ///< The root JSON value for the currently read message. + JSONValue m_jsonRoot; ///< The root JSON value for the currently read message. + + CallStyle m_defaultCallStyle = CallStyle::Array; ///< The default calling style - CallStyle m_defaultCallStyle = CallStyle::Array; ///< The default calling style - RttiTypeFuncsMap m_typeMap; - Int m_terminationTimeOutInMs = 1 * 1000; ///< Time to wait for termination response. Default is 1 second + Int m_terminationTimeOutInMs = + 1 * 1000; ///< Time to wait for termination response. Default is 1 second }; // --------------------------------------------------------------------------- -template -SlangResult JSONRPCConnection::toValidNativeOrSendError(const JSONValue& value, T* data, const JSONValue& id) +template +SlangResult JSONRPCConnection::toValidNativeOrSendError( + const JSONValue& value, + T* data, + const JSONValue& id) { const RttiInfo* rttiInfo = GetRttiInfo::get(); @@ -191,7 +270,10 @@ SlangResult JSONRPCConnection::toValidNativeOrSendError(const JSONValue& value, if (rttiInfo->isNamed()) { const NamedRttiInfo* namedRttiInfo = static_cast(rttiInfo); - m_diagnosticSink.diagnose(SourceLoc(), JSONDiagnostics::argsAreInvalid, namedRttiInfo->m_name); + m_diagnosticSink.diagnose( + SourceLoc(), + JSONDiagnostics::argsAreInvalid, + namedRttiInfo->m_name); } return sendError(JSONRPC::ErrorCode::InvalidRequest, id); @@ -202,4 +284,3 @@ SlangResult JSONRPCConnection::toValidNativeOrSendError(const JSONValue& value, } // namespace Slang #endif // SLANG_COMPILER_CORE_JSON_RPC_CONNECTION_H - diff --git a/source/compiler-core/slang-json-rpc.cpp b/source/compiler-core/slang-json-rpc.cpp index f4a61da1e..bf96edefa 100644 --- a/source/compiler-core/slang-json-rpc.cpp +++ b/source/compiler-core/slang-json-rpc.cpp @@ -1,17 +1,18 @@ #include "slang-json-rpc.h" #include "slang-com-helper.h" - #include "slang-json-native.h" -namespace Slang { +namespace Slang +{ // https://www.jsonrpc.org/specification /* static */ const UnownedStringSlice JSONRPC::jsonRpc = UnownedStringSlice::fromLiteral("jsonrpc"); -/* static */const UnownedStringSlice JSONRPC::jsonRpcVersion = UnownedStringSlice::fromLiteral("2.0"); -/* static */const UnownedStringSlice JSONRPC::id = UnownedStringSlice::fromLiteral("id"); +/* static */ const UnownedStringSlice JSONRPC::jsonRpcVersion = + UnownedStringSlice::fromLiteral("2.0"); +/* static */ const UnownedStringSlice JSONRPC::id = UnownedStringSlice::fromLiteral("id"); static const auto g_result = UnownedStringSlice::fromLiteral("result"); static const auto g_error = UnownedStringSlice::fromLiteral("error"); @@ -29,7 +30,8 @@ static const StructRttiInfo _makeJSONRPCErrorResponse_ErrorRtti() builder.addField("message", &obj.message); return builder.make(); } -/* static */const StructRttiInfo JSONRPCErrorResponse::Error::g_rttiInfo = _makeJSONRPCErrorResponse_ErrorRtti(); +/* static */ const StructRttiInfo JSONRPCErrorResponse::Error::g_rttiInfo = + _makeJSONRPCErrorResponse_ErrorRtti(); static const StructRttiInfo _makeJSONRPCErrorResponseRtti() { @@ -43,7 +45,8 @@ static const StructRttiInfo _makeJSONRPCErrorResponseRtti() return builder.make(); } -/* static */const StructRttiInfo JSONRPCErrorResponse::g_rttiInfo = _makeJSONRPCErrorResponseRtti(); +/* static */ const StructRttiInfo JSONRPCErrorResponse::g_rttiInfo = + _makeJSONRPCErrorResponseRtti(); static const StructRttiInfo _makeJSONRPCCallResponseRtti() { @@ -58,7 +61,7 @@ static const StructRttiInfo _makeJSONRPCCallResponseRtti() return builder.make(); } -/* static */const StructRttiInfo JSONRPCCall::g_rttiInfo = _makeJSONRPCCallResponseRtti(); +/* static */ const StructRttiInfo JSONRPCCall::g_rttiInfo = _makeJSONRPCCallResponseRtti(); static const StructRttiInfo _makeJSONResultResponseResponseRtti() { @@ -71,9 +74,12 @@ static const StructRttiInfo _makeJSONResultResponseResponseRtti() return builder.make(); } -/* static */const StructRttiInfo JSONResultResponse::g_rttiInfo = _makeJSONResultResponseResponseRtti(); +/* static */ const StructRttiInfo JSONResultResponse::g_rttiInfo = + _makeJSONResultResponseResponseRtti(); -/* static */JSONRPCMessageType JSONRPCUtil::getMessageType(JSONContainer* container, const JSONValue& value) +/* static */ JSONRPCMessageType JSONRPCUtil::getMessageType( + JSONContainer* container, + const JSONValue& value) { if (value.getKind() == JSONValue::Kind::Object) { @@ -103,13 +109,18 @@ static const StructRttiInfo _makeJSONResultResponseResponseRtti() return JSONRPCMessageType::Invalid; } -/* static */SlangResult JSONRPCUtil::parseJSON(const UnownedStringSlice& slice, JSONContainer* container, DiagnosticSink* sink, JSONValue& outValue) +/* static */ SlangResult JSONRPCUtil::parseJSON( + const UnownedStringSlice& slice, + JSONContainer* container, + DiagnosticSink* sink, + JSONValue& outValue) { SourceManager* sourceManager = sink->getSourceManager(); // Now need to parse as JSON String contents(slice); - SourceFile* sourceFile = sourceManager->createSourceFileWithString(PathInfo::makeUnknown(), contents); + SourceFile* sourceFile = + sourceManager->createSourceFileWithString(PathInfo::makeUnknown(), contents); SourceView* sourceView = sourceManager->createSourceView(sourceFile, nullptr, SourceLoc()); JSONLexer lexer; @@ -124,7 +135,12 @@ static const StructRttiInfo _makeJSONResultResponseResponseRtti() return SLANG_OK; } -/* static */SlangResult JSONRPCUtil::convertToNative(JSONContainer* container, const JSONValue& value, DiagnosticSink* sink, const RttiInfo* rttiInfo, void* out) +/* static */ SlangResult JSONRPCUtil::convertToNative( + JSONContainer* container, + const JSONValue& value, + DiagnosticSink* sink, + const RttiInfo* rttiInfo, + void* out) { auto typeMap = JSONNativeUtil::getTypeFuncsMap(); @@ -133,7 +149,11 @@ static const StructRttiInfo _makeJSONResultResponseResponseRtti() return SLANG_OK; } -/* static */SlangResult JSONRPCUtil::convertToJSON(const RttiInfo* rttiInfo, const void* in, DiagnosticSink* sink, StringBuilder& out) +/* static */ SlangResult JSONRPCUtil::convertToJSON( + const RttiInfo* rttiInfo, + const void* in, + DiagnosticSink* sink, + StringBuilder& out) { SourceManager* sourceManager = sink->getSourceManager(); JSONContainer container(sourceManager); @@ -153,7 +173,7 @@ static const StructRttiInfo _makeJSONResultResponseResponseRtti() return SLANG_OK; } -/* static */JSONValue JSONRPCUtil::getId(JSONContainer* container, const JSONValue& root) +/* static */ JSONValue JSONRPCUtil::getId(JSONContainer* container, const JSONValue& root) { if (root.getKind() == JSONValue::Kind::Object) { @@ -162,7 +182,8 @@ static const StructRttiInfo _makeJSONResultResponseResponseRtti() if (key != JSONKey(0)) { auto obj = container->getObject(root); - Index index = obj.findFirstIndex([key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); + Index index = obj.findFirstIndex( + [key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); if (index >= 0) { diff --git a/source/compiler-core/slang-json-rpc.h b/source/compiler-core/slang-json-rpc.h index 6baba7829..b9140934f 100644 --- a/source/compiler-core/slang-json-rpc.h +++ b/source/compiler-core/slang-json-rpc.h @@ -1,29 +1,28 @@ #ifndef SLANG_COMPILER_CORE_JSON_RPC_H #define SLANG_COMPILER_CORE_JSON_RPC_H -#include "slang.h" +#include "../core/slang-http.h" #include "slang-com-helper.h" #include "slang-com-ptr.h" - -#include "slang-json-value.h" - #include "slang-json-parser.h" -#include "../core/slang-http.h" +#include "slang-json-value.h" +#include "slang.h" -namespace Slang { +namespace Slang +{ /// Struct to hold values associated with JSON-RPC struct JSONRPC { enum class ErrorCode { - ParseError = -32700, ///< Invalid JSON was received by the server. - InvalidRequest = -32600, ///< The JSON sent is not a valid Request object. - MethodNotFound = -32601, ///< The method does not exist / is not available. - InvalidParams = -32602, ///< Invalid method parameter(s). - InternalError = -32603, ///< Internal JSON - RPC error. + ParseError = -32700, ///< Invalid JSON was received by the server. + InvalidRequest = -32600, ///< The JSON sent is not a valid Request object. + MethodNotFound = -32601, ///< The method does not exist / is not available. + InvalidParams = -32602, ///< Invalid method parameter(s). + InternalError = -32603, ///< Internal JSON - RPC error. - ServerImplStart = -32000, ///< Server implementation defined error range + ServerImplStart = -32000, ///< Server implementation defined error range ServerImplEnd = -32099, }; @@ -32,9 +31,9 @@ struct JSONRPC auto kind = value.getKind(); switch (kind) { - case JSONValue::Kind::Integer: - case JSONValue::Kind::Invalid: - case JSONValue::Kind::String: + case JSONValue::Kind::Integer: + case JSONValue::Kind::Invalid: + case JSONValue::Kind::String: { return true; } @@ -53,30 +52,36 @@ struct JSONRPCErrorResponse { bool isValid() const { return code != 0; } - Int code = 0; ///< Value from ErrorCode - UnownedStringSlice message; ///< Error message - + Int code = 0; ///< Value from ErrorCode + UnownedStringSlice message; ///< Error message + static const StructRttiInfo g_rttiInfo; }; - bool isValid() const { return jsonrpc == JSONRPC::jsonRpcVersion && error.isValid() && JSONRPC::isIdOk(id); } + bool isValid() const + { + return jsonrpc == JSONRPC::jsonRpcVersion && error.isValid() && JSONRPC::isIdOk(id); + } UnownedStringSlice jsonrpc = JSONRPC::jsonRpcVersion; Error error; - JSONValue data; ///< Optional data describing the errro - JSONValue id; ///< Id associated with this request + JSONValue data; ///< Optional data describing the errro + JSONValue id; ///< Id associated with this request static const StructRttiInfo g_rttiInfo; }; struct JSONRPCCall { - bool isValid() const { return method.getLength() > 0 && jsonrpc == JSONRPC::jsonRpcVersion && JSONRPC::isIdOk(id); } + bool isValid() const + { + return method.getLength() > 0 && jsonrpc == JSONRPC::jsonRpcVersion && JSONRPC::isIdOk(id); + } UnownedStringSlice jsonrpc = JSONRPC::jsonRpcVersion; - UnownedStringSlice method; ///< The name of the method - JSONValue params; ///< Can be invalid/array/object - JSONValue id; ///< Id associated with this request + UnownedStringSlice method; ///< The name of the method + JSONValue params; ///< Can be invalid/array/object + JSONValue id; ///< Id associated with this request static const StructRttiInfo g_rttiInfo; }; @@ -86,8 +91,8 @@ struct JSONResultResponse bool isValid() const { return jsonrpc == JSONRPC::jsonRpcVersion && JSONRPC::isIdOk(id); } UnownedStringSlice jsonrpc = JSONRPC::jsonRpcVersion; - JSONValue result; ///< The result value - JSONValue id; ///< Id associated with this request + JSONValue result; ///< The result value + JSONValue id; ///< Id associated with this request static const StructRttiInfo g_rttiInfo; }; @@ -105,30 +110,50 @@ enum class JSONRPCMessageType class JSONRPCUtil { public: - - /// Determine the response type + /// Determine the response type static JSONRPCMessageType getMessageType(JSONContainer* container, const JSONValue& value); - /// Parse slice into JSONContainer. outValue is the root of the hierarchy. - /// NOTE! Uses and *assumes* there is a source manager on the sink. outValue is likely only usable whilst the sourceManger is in scope - /// The sourceLoc can only be interpretted with the sourceLoc anyway - static SlangResult parseJSON(const UnownedStringSlice& slice, JSONContainer* container, DiagnosticSink* sink, JSONValue& outValue); - - /// Convert value into out - static SlangResult convertToNative(JSONContainer* container, const JSONValue& value, DiagnosticSink* sink, const RttiInfo* rttiInfo, void* out); - template - static SlangResult convertToNative(JSONContainer* container, const JSONValue& value, DiagnosticSink* sink, T& out) { return convertToNative(container, value, sink, GetRttiInfo::get(), (void*)&out); } + /// Parse slice into JSONContainer. outValue is the root of the hierarchy. + /// NOTE! Uses and *assumes* there is a source manager on the sink. outValue is likely only + /// usable whilst the sourceManger is in scope The sourceLoc can only be interpretted with the + /// sourceLoc anyway + static SlangResult parseJSON( + const UnownedStringSlice& slice, + JSONContainer* container, + DiagnosticSink* sink, + JSONValue& outValue); + + /// Convert value into out + static SlangResult convertToNative( + JSONContainer* container, + const JSONValue& value, + DiagnosticSink* sink, + const RttiInfo* rttiInfo, + void* out); + template + static SlangResult convertToNative( + JSONContainer* container, + const JSONValue& value, + DiagnosticSink* sink, + T& out) + { + return convertToNative(container, value, sink, GetRttiInfo::get(), (void*)&out); + } - /// Convert to JSON - static SlangResult convertToJSON(const RttiInfo* rttiInfo, const void* in, DiagnosticSink* sink, StringBuilder& out); + /// Convert to JSON + static SlangResult convertToJSON( + const RttiInfo* rttiInfo, + const void* in, + DiagnosticSink* sink, + StringBuilder& out); - template + template static SlangResult convertToJSON(const T* in, DiagnosticSink* sink, StringBuilder& out) { return convertToJSON(GetRttiInfo::get(), (const void*)in, sink, out); } - /// Get an id directly from root (assumed id: is in root object definition). + /// Get an id directly from root (assumed id: is in root object definition). static JSONValue getId(JSONContainer* container, const JSONValue& root); }; diff --git a/source/compiler-core/slang-json-source-map-util.cpp b/source/compiler-core/slang-json-source-map-util.cpp index f66ee50da..99fe25546 100644 --- a/source/compiler-core/slang-json-source-map-util.cpp +++ b/source/compiler-core/slang-json-source-map-util.cpp @@ -1,21 +1,22 @@ #include "slang-json-source-map-util.h" -#include "slang-com-helper.h" - -#include "../core/slang-string-util.h" #include "../core/slang-blob.h" - +#include "../core/slang-string-util.h" +#include "slang-com-helper.h" #include "slang-json-native.h" -namespace Slang { +namespace Slang +{ /* -Support for source maps. Source maps provide a standardized mechanism to associate a location in one output file -with another. +Support for source maps. Source maps provide a standardized mechanism to associate a location in one +output file with another. -* [Source Map Proposal](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?hl=en_US&pli=1&pli=1) +* [Source Map +Proposal](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?hl=en_US&pli=1&pli=1) * [Chrome Source Map post](https://developer.chrome.com/blog/sourcemaps/) -* [Base64 VLQs in Source Maps](https://www.lucidchart.com/techblog/2019/08/22/decode-encoding-base64-vlqs-source-maps/) +* [Base64 VLQs in Source +Maps](https://www.lucidchart.com/techblog/2019/08/22/decode-encoding-base64-vlqs-source-maps/) Example... @@ -30,7 +31,8 @@ Example... } */ -namespace { // anonymous +namespace +{ // anonymous struct JSONSourceMap { @@ -38,14 +40,16 @@ struct JSONSourceMap int32_t version = 3; /// An optional name of the generated code that this source map is associated with. String file; - /// An optional source root, useful for relocating source files on a server or removing repeated values in - /// the “sources” entry. This value is prepended to the individual entries in the “source” field. + /// An optional source root, useful for relocating source files on a server or removing repeated + /// values in the “sources” entry. This value is prepended to the individual entries in the + /// “source” field. String sourceRoot; /// A list of original sources used by the “mappings” entry. List sources; - /// An optional list of source content, useful when the “source” can’t be hosted. The contents are listed in the same order as the sources in line 5. - /// “null” may be used if some original sources should be retrieved by name. - /// Because could be a string or nullptr, we use JSONValue to hold value. + /// An optional list of source content, useful when the “source” can’t be hosted. The contents + /// are listed in the same order as the sources in line 5. “null” may be used if some original + /// sources should be retrieved by name. Because could be a string or nullptr, we use JSONValue + /// to hold value. List sourcesContent; /// A list of symbol names used by the “mappings” entry. List names; @@ -55,7 +59,7 @@ struct JSONSourceMap static const StructRttiInfo g_rttiInfo; }; -} // anonymous +} // namespace static const StructRttiInfo _makeJSONSourceMap_Rtti() { @@ -73,10 +77,11 @@ static const StructRttiInfo _makeJSONSourceMap_Rtti() return builder.make(); } -/* static */const StructRttiInfo JSONSourceMap::g_rttiInfo = _makeJSONSourceMap_Rtti(); +/* static */ const StructRttiInfo JSONSourceMap::g_rttiInfo = _makeJSONSourceMap_Rtti(); // Encode a 6 bit value to VLQ encoding -static const unsigned char g_vlqEncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const unsigned char g_vlqEncodeTable[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; struct VlqDecodeTable { @@ -88,19 +93,22 @@ struct VlqDecodeTable map[g_vlqEncodeTable[i]] = int8_t(i); } } - /// Returns a *negative* value if invalid - SLANG_FORCE_INLINE int8_t operator[](unsigned char c) const { return (c & ~char(0x7f)) ? -1 : map[c]; } + /// Returns a *negative* value if invalid + SLANG_FORCE_INLINE int8_t operator[](unsigned char c) const + { + return (c & ~char(0x7f)) ? -1 : map[c]; + } int8_t map[128]; }; static const VlqDecodeTable g_vlqDecodeTable; -/* +/* https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?hl=en_US&pli=1&pli=1# -The VLQ is a Base64 value, where the most significant bit (the 6th bit) is used as the continuation -bit, and the “digits” are encoded into the string least significant first, and where the least significant -bit of the first digit is used as the sign bit. */ +The VLQ is a Base64 value, where the most significant bit (the 6th bit) is used as the continuation +bit, and the “digits” are encoded into the string least significant first, and where the least +significant bit of the first digit is used as the sign bit. */ static SlangResult _decode(UnownedStringSlice& ioEncoded, Index& out) { @@ -125,12 +133,11 @@ static SlangResult _decode(UnownedStringSlice& ioEncoded, Index& out) { return SLANG_FAIL; } - + v += (decodeValue & 0x1f) << shift; shift += 5; - } - while (decodeValue & 0x20); + } while (decodeValue & 0x20); } // Save out the remaining part @@ -148,31 +155,34 @@ void _encode(Index v, StringBuilder& out) // We want to make v always positive to encode // we use the last bit to indicate negativity - v = (v < 0) ? (1 - v) : v; - + v = (v < 0) ? (1 - v) : v; + // We'll use a simple buffer, so as to not have to constantly update he StringBuffer char dst[8]; char* cur = dst; - do + do { const Index nextV = v >> 5; const Index encodeValue = (v & 0x1f) + (nextV ? 0x20 : 0); // Encode 5 bits, plus continuation bit char c = g_vlqEncodeTable[encodeValue]; - + // Save the char *cur++ = c; - + v = nextV; - } - while (v); + } while (v); out.append(dst, cur); } -/* static */SlangResult JSONSourceMapUtil::decode(JSONContainer* container, JSONValue root, DiagnosticSink* sink, SourceMap& outSourceMap) +/* static */ SlangResult JSONSourceMapUtil::decode( + JSONContainer* container, + JSONValue root, + DiagnosticSink* sink, + SourceMap& outSourceMap) { outSourceMap.clear(); @@ -192,7 +202,7 @@ void _encode(Index v, StringBuilder& out) outSourceMap.m_sourceRoot = native.sourceRoot; const Count sourcesCount = native.sources.getCount(); - + // These should all be unique, but for simplicity, we build a table outSourceMap.m_sources.setCount(sourcesCount); for (Index i = 0; i < sourcesCount; ++i) @@ -237,10 +247,10 @@ void _encode(Index v, StringBuilder& out) List lines; StringUtil::split(native.mappings, ';', lines); - + List segments; - // Index into sources + // Index into sources Index sourceFileIndex = 0; Index sourceLine = 0; @@ -280,9 +290,17 @@ void _encode(Index v, StringBuilder& out) // It can be 4 or 5 parts if (segment.getLength()) { - /* If present, an zero-based index into the "sources" list. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. - If present, the zero-based starting line in the original source represented. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. Always present if there is a source field. - If present, the zero-based starting column of the line in the source represented. This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence of this field, in which case the whole value is represented. Always present if there is a source field. + /* If present, an zero-based index into the "sources" list. This field is a base 64 + VLQ relative to the previous occurrence of this field, unless this is the first + occurrence of this field, in which case the whole value is represented. If + present, the zero-based starting line in the original source represented. This + field is a base 64 VLQ relative to the previous occurrence of this field, unless + this is the first occurrence of this field, in which case the whole value is + represented. Always present if there is a source field. If present, the + zero-based starting column of the line in the source represented. This field is a + base 64 VLQ relative to the previous occurrence of this field, unless this is the + first occurrence of this field, in which case the whole value is represented. + Always present if there is a source field. */ Index sourceFileDelta; @@ -304,9 +322,10 @@ void _encode(Index v, StringBuilder& out) // 5 parts if (segment.getLength() > 0) { - /* If present, the zero - based index into the "names" list associated with this segment. - This field is a base 64 VLQ relative to the previous occurrence of this field, unless this is the first occurrence - of this field, in which case the whole value is represented. + /* If present, the zero - based index into the "names" list associated with this + segment. This field is a base 64 VLQ relative to the previous occurrence of this + field, unless this is the first occurrence of this field, in which case the + whole value is represented. */ Index nameDelta; @@ -334,7 +353,11 @@ void _encode(Index v, StringBuilder& out) return SLANG_OK; } -SlangResult JSONSourceMapUtil::encode(const SourceMap& sourceMap, JSONContainer* container, DiagnosticSink* sink, JSONValue& outValue) +SlangResult JSONSourceMapUtil::encode( + const SourceMap& sourceMap, + JSONContainer* container, + DiagnosticSink* sink, + JSONValue& outValue) { // Convert to native JSONSourceMap native; @@ -359,10 +382,11 @@ SlangResult JSONSourceMapUtil::encode(const SourceMap& sourceMap, JSONContainer* for (Index i = 0; i < count; ++i) { const auto srcValue = sourceMap.m_sourcesContent[i]; - - const JSONValue dstValue = (srcValue == StringSlicePool::kNullHandle) ? - native.sourcesContent[i] = JSONValue::makeNull() : - container->createString(sourceMap.m_slicePool.getSlice(srcValue)); + + const JSONValue dstValue = + (srcValue == StringSlicePool::kNullHandle) + ? native.sourcesContent[i] = JSONValue::makeNull() + : container->createString(sourceMap.m_slicePool.getSlice(srcValue)); native.sourcesContent[i] = dstValue; } @@ -408,7 +432,7 @@ SlangResult JSONSourceMapUtil::encode(const SourceMap& sourceMap, JSONContainer* // We reset the generated column index at the start of each new generated line Index generatedColumn = 0; - + for (Index j = 0; j < entriesCount; ++j) { auto entry = entries[j]; @@ -459,18 +483,22 @@ SlangResult JSONSourceMapUtil::encode(const SourceMap& sourceMap, JSONContainer* RttiTypeFuncsMap typeMap = JSONNativeUtil::getTypeFuncsMap(); NativeToJSONConverter converter(container, &typeMap, sink); - SLANG_RETURN_ON_FAIL(converter.convert(GetRttiInfo::get(), &native, outValue)); + SLANG_RETURN_ON_FAIL( + converter.convert(GetRttiInfo::get(), &native, outValue)); } return SLANG_OK; } -/* static */SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, SourceMap& outSourceMap) +/* static */ SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, SourceMap& outSourceMap) { return read(blob, nullptr, outSourceMap); } -SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, DiagnosticSink* parentSink, SourceMap& outSourceMap) +SlangResult JSONSourceMapUtil::read( + ISlangBlob* blob, + DiagnosticSink* parentSink, + SourceMap& outSourceMap) { outSourceMap.clear(); @@ -485,7 +513,8 @@ SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, DiagnosticSink* parentSink JSONValue rootValue; { // Now need to parse as JSON - SourceFile* sourceFile = sourceManager.createSourceFileWithBlob(PathInfo::makeUnknown(), blob); + SourceFile* sourceFile = + sourceManager.createSourceFileWithBlob(PathInfo::makeUnknown(), blob); SourceView* sourceView = sourceManager.createSourceView(sourceFile, nullptr, SourceLoc()); JSONLexer lexer; @@ -505,7 +534,9 @@ SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, DiagnosticSink* parentSink } -/* static */SlangResult JSONSourceMapUtil::write(const SourceMap& sourceMap, ComPtr& outBlob) +/* static */ SlangResult JSONSourceMapUtil::write( + const SourceMap& sourceMap, + ComPtr& outBlob) { SourceManager sourceMapSourceManager; sourceMapSourceManager.initialize(nullptr, nullptr); @@ -517,7 +548,10 @@ SlangResult JSONSourceMapUtil::read(ISlangBlob* blob, DiagnosticSink* parentSink return SLANG_OK; } -/* static */ SlangResult JSONSourceMapUtil::write(const SourceMap& sourceMap, DiagnosticSink* sink, ComPtr& outBlob) +/* static */ SlangResult JSONSourceMapUtil::write( + const SourceMap& sourceMap, + DiagnosticSink* sink, + ComPtr& outBlob) { auto sourceManager = sink->getSourceManager(); diff --git a/source/compiler-core/slang-json-source-map-util.h b/source/compiler-core/slang-json-source-map-util.h index d61936ce4..0e6f4248c 100644 --- a/source/compiler-core/slang-json-source-map-util.h +++ b/source/compiler-core/slang-json-source-map-util.h @@ -1,29 +1,40 @@ #ifndef SLANG_COMPILER_CORE_JSON_SOURCE_MAP_UTIL_H #define SLANG_COMPILER_CORE_JSON_SOURCE_MAP_UTIL_H -#include "slang-source-map.h" - #include "slang-json-value.h" +#include "slang-source-map.h" -namespace Slang { - -struct JSONSourceMapUtil +namespace Slang { - /// Decode from root into the source map - static SlangResult decode(JSONContainer* container, JSONValue root, DiagnosticSink* sink, SourceMap& out); - - /// Converts the source map contents into JSON - static SlangResult encode(const SourceMap& sourceMap, JSONContainer* container, DiagnosticSink* sink, JSONValue& outValue); - /// Read the blob (encoded as JSON) as a source map. - /// Sink is optional, and can be passed as nullptr +struct JSONSourceMapUtil +{ + /// Decode from root into the source map + static SlangResult decode( + JSONContainer* container, + JSONValue root, + DiagnosticSink* sink, + SourceMap& out); + + /// Converts the source map contents into JSON + static SlangResult encode( + const SourceMap& sourceMap, + JSONContainer* container, + DiagnosticSink* sink, + JSONValue& outValue); + + /// Read the blob (encoded as JSON) as a source map. + /// Sink is optional, and can be passed as nullptr static SlangResult read(ISlangBlob* blob, DiagnosticSink* sink, SourceMap& outSourceMap); static SlangResult read(ISlangBlob* blob, SourceMap& outSourceMap); - /// Write source map to outBlob JSON + /// Write source map to outBlob JSON static SlangResult write(const SourceMap& sourceMap, ComPtr& outBlob); - /// Write out the source map into a blob - static SlangResult write(const SourceMap& sourceMap, DiagnosticSink* sink, ComPtr& outBlob); + /// Write out the source map into a blob + static SlangResult write( + const SourceMap& sourceMap, + DiagnosticSink* sink, + ComPtr& outBlob); }; } // namespace Slang diff --git a/source/compiler-core/slang-json-value.cpp b/source/compiler-core/slang-json-value.cpp index 2e1eb6812..2738058ee 100644 --- a/source/compiler-core/slang-json-value.cpp +++ b/source/compiler-core/slang-json-value.cpp @@ -4,28 +4,28 @@ #include "../core/slang-string-escape-util.h" #include "../core/slang-string-util.h" -namespace Slang { - -/* static */const JSONValue::Kind JSONValue::g_typeToKind[] = +namespace Slang { - JSONValue::Kind::Invalid, // Invalid - JSONValue::Kind::Bool, // True, - JSONValue::Kind::Bool, // False - JSONValue::Kind::Null, // Null, +/* static */ const JSONValue::Kind JSONValue::g_typeToKind[] = { + JSONValue::Kind::Invalid, // Invalid + + JSONValue::Kind::Bool, // True, + JSONValue::Kind::Bool, // False + JSONValue::Kind::Null, // Null, - JSONValue::Kind::String, // StringLexeme, - JSONValue::Kind::Integer, // IntegerLexeme, - JSONValue::Kind::Float, // FloatLexeme, + JSONValue::Kind::String, // StringLexeme, + JSONValue::Kind::Integer, // IntegerLexeme, + JSONValue::Kind::Float, // FloatLexeme, - JSONValue::Kind::Integer, // IntegerValue, - JSONValue::Kind::Float, // FloatValue, - JSONValue::Kind::String, // StringValue, + JSONValue::Kind::Integer, // IntegerValue, + JSONValue::Kind::Float, // FloatValue, + JSONValue::Kind::String, // StringValue, - JSONValue::Kind::String, // StringRepresentation + JSONValue::Kind::String, // StringRepresentation - JSONValue::Kind::Array, // Array, - JSONValue::Kind::Object, // Object, + JSONValue::Kind::Array, // Array, + JSONValue::Kind::Object, // Object, }; static bool _isDefault(const RttiInfo* type, const void* in) @@ -44,7 +44,7 @@ static OtherRttiInfo _getJSONValueRttiInfo() info.m_typeFuncs = GetRttiTypeFuncs::getFuncs(); return info; } -/* static */const OtherRttiInfo JSONValue::g_rttiInfo = _getJSONValueRttiInfo(); +/* static */ const OtherRttiInfo JSONValue::g_rttiInfo = _getJSONValueRttiInfo(); static JSONKeyValue _makeInvalidKeyValue() { @@ -54,7 +54,7 @@ static JSONKeyValue _makeInvalidKeyValue() return keyValue; } -/* static */JSONKeyValue g_invalid = _makeInvalidKeyValue(); +/* static */ JSONKeyValue g_invalid = _makeInvalidKeyValue(); /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -66,15 +66,15 @@ bool JSONValue::asBool() const { switch (type) { - case JSONValue::Type::True: return true; - case JSONValue::Type::False: - case JSONValue::Type::Null: + case JSONValue::Type::True: return true; + case JSONValue::Type::False: + case JSONValue::Type::Null: { return false; } - case JSONValue::Type::IntegerValue: return intValue != 0; - case JSONValue::Type::FloatValue: return floatValue != 0; - default: break; + case JSONValue::Type::IntegerValue: return intValue != 0; + case JSONValue::Type::FloatValue: return floatValue != 0; + default: break; } if (isLexeme(type)) @@ -85,7 +85,7 @@ bool JSONValue::asBool() const { SLANG_ASSERT(!"Not bool convertable"); } - + return false; } @@ -93,15 +93,14 @@ int64_t JSONValue::asInteger() const { switch (type) { - case JSONValue::Type::True: return 1; - case JSONValue::Type::False: - case JSONValue::Type::Null: + case JSONValue::Type::True: return 1; + case JSONValue::Type::False: + case JSONValue::Type::Null: { return 0; } - case JSONValue::Type::IntegerValue: return intValue; - case JSONValue::Type::FloatValue: return int64_t(floatValue); - break; + case JSONValue::Type::IntegerValue: return intValue; + case JSONValue::Type::FloatValue: return int64_t(floatValue); break; } if (isLexeme(type)) @@ -120,15 +119,15 @@ double JSONValue::asFloat() const { switch (type) { - case JSONValue::Type::True: return 1.0; - case JSONValue::Type::False: - case JSONValue::Type::Null: + case JSONValue::Type::True: return 1.0; + case JSONValue::Type::False: + case JSONValue::Type::Null: { return 0.0; } - case JSONValue::Type::IntegerValue: return double(intValue); - case JSONValue::Type::FloatValue: return floatValue; - default: break; + case JSONValue::Type::IntegerValue: return double(intValue); + case JSONValue::Type::FloatValue: return floatValue; + default: break; } if (isLexeme(type)) @@ -139,7 +138,7 @@ double JSONValue::asFloat() const { SLANG_ASSERT(!"Not float convertable"); } - + return 0; } @@ -197,7 +196,8 @@ UnownedStringSlice PersistentJSONValue::getSlice() const void PersistentJSONValue::set(const UnownedStringSlice& slice, SourceLoc inLoc) { - StringRepresentation* oldRep = (type == JSONValue::Type::StringRepresentation) ? stringRep : nullptr; + StringRepresentation* oldRep = + (type == JSONValue::Type::StringRepresentation) ? stringRep : nullptr; type = Type::StringRepresentation; loc = inLoc; @@ -205,13 +205,11 @@ void PersistentJSONValue::set(const UnownedStringSlice& slice, SourceLoc inLoc) StringRepresentation* newRep = nullptr; const auto sliceLength = slice.getLength(); - + // If we have an oldRep that is unique and large enough reuse it if (sliceLength) { - if (oldRep && - oldRep->isUniquelyReferenced() && - sliceLength <= oldRep->capacity) + if (oldRep && oldRep->isUniquelyReferenced() && sliceLength <= oldRep->capacity) { oldRep->setContents(slice); newRep = oldRep; @@ -220,7 +218,7 @@ void PersistentJSONValue::set(const UnownedStringSlice& slice, SourceLoc inLoc) } else { - newRep = StringRepresentation::createWithReference(slice); + newRep = StringRepresentation::createWithReference(slice); } SLANG_ASSERT(newRep->debugGetReferenceCount() >= 1); @@ -248,25 +246,24 @@ bool PersistentJSONValue::operator==(const ThisType& rhs) const return true; } - if (type != rhs.type || - loc != rhs.loc) + if (type != rhs.type || loc != rhs.loc) { return false; } switch (type) { - case Type::Invalid: - case Type::True: - case Type::False: - case Type::Null: + case Type::Invalid: + case Type::True: + case Type::False: + case Type::Null: { // The type is all that needs to be checked return true; } - case Type::IntegerValue: return intValue == rhs.intValue; - case Type::FloatValue: return floatValue == rhs.floatValue; - case Type::StringRepresentation: + case Type::IntegerValue: return intValue == rhs.intValue; + case Type::FloatValue: return floatValue == rhs.floatValue; + case Type::StringRepresentation: { if (stringRep == rhs.stringRep) { @@ -276,7 +273,7 @@ bool PersistentJSONValue::operator==(const ThisType& rhs) const auto rhsSlice = StringRepresentation::asSlice(rhs.stringRep); return thisSlice == rhsSlice; } - default: break; + default: break; } SLANG_ASSERT(!"Not valid Persistent type"); @@ -290,8 +287,8 @@ void PersistentJSONValue::_init(const JSONValue& in, JSONContainer* container) switch (in.type) { - case Type::StringValue: - case Type::StringLexeme: + case Type::StringValue: + case Type::StringLexeme: { if (!container) { @@ -301,7 +298,7 @@ void PersistentJSONValue::_init(const JSONValue& in, JSONContainer* container) _init(container->getTransientString(in), in.loc); break; } - case Type::StringRepresentation: + case Type::StringRepresentation: { *(JSONValue*)this = in; if (stringRep) @@ -310,27 +307,27 @@ void PersistentJSONValue::_init(const JSONValue& in, JSONContainer* container) } break; } - case Type::IntegerLexeme: + case Type::IntegerLexeme: { type = JSONValue::Type::IntegerValue; intValue = container->asInteger(in); loc = in.loc; break; } - case Type::FloatLexeme: + case Type::FloatLexeme: { type = JSONValue::Type::FloatValue; floatValue = container->asFloat(in); loc = in.loc; break; } - case Type::Array: - case Type::Object: + case Type::Array: + case Type::Object: { SLANG_ASSERT(!"Not a simple JSON type"); break; } - default: + default: { *(JSONValue*)this = in; break; @@ -364,9 +361,8 @@ void PersistentJSONValue::set(const JSONValue& in, JSONContainer* container) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -JSONContainer::JSONContainer(SourceManager* sourceManager): - m_slicePool(StringSlicePool::Style::Default), - m_sourceManager(sourceManager) +JSONContainer::JSONContainer(SourceManager* sourceManager) + : m_slicePool(StringSlicePool::Style::Default), m_sourceManager(sourceManager) { // Index 0 is the empty array or object _addRange(Range::Type::None, 0, 0); @@ -385,7 +381,7 @@ void JSONContainer::reset() m_currentView = nullptr; } -/* static */bool JSONContainer::areKeysUnique(const JSONKeyValue* keyValues, Index keyValueCount) +/* static */ bool JSONContainer::areKeysUnique(const JSONKeyValue* keyValues, Index keyValueCount) { for (Index i = 1; i < keyValueCount; ++i) { @@ -447,7 +443,10 @@ JSONValue JSONContainer::createArray(const JSONValue* values, Index valuesCount, return value; } -JSONValue JSONContainer::createObject(const JSONKeyValue* keyValues, Index keyValueCount, SourceLoc loc) +JSONValue JSONContainer::createObject( + const JSONKeyValue* keyValues, + Index keyValueCount, + SourceLoc loc) { if (keyValueCount <= 0) { @@ -514,7 +513,9 @@ ArrayView JSONContainer::getArray(const JSONValue& in) return ArrayView((JSONValue*)nullptr, 0); } const Range& range = m_ranges[in.rangeIndex]; - SLANG_ASSERT(range.startIndex <= m_arrayValues.getCount() && range.startIndex + range.count <= m_arrayValues.getCount()); + SLANG_ASSERT( + range.startIndex <= m_arrayValues.getCount() && + range.startIndex + range.count <= m_arrayValues.getCount()); return ArrayView(m_arrayValues.getBuffer() + range.startIndex, range.count); } @@ -558,27 +559,27 @@ UnownedStringSlice JSONContainer::getString(const JSONValue& in) { switch (in.type) { - case JSONValue::Type::StringValue: + case JSONValue::Type::StringValue: { return getStringFromKey(in.stringKey); } - case JSONValue::Type::StringLexeme: + case JSONValue::Type::StringLexeme: { auto slice = getTransientString(in); auto handle = m_slicePool.add(slice); return m_slicePool.getSlice(handle); } - case JSONValue::Type::StringRepresentation: + case JSONValue::Type::StringRepresentation: { return StringRepresentation::asSlice(in.stringRep); } - case JSONValue::Type::Null: + case JSONValue::Type::Null: { return UnownedStringSlice(); } - default: break; + default: break; } - + SLANG_ASSERT(!"Not a string type"); return UnownedStringSlice(); } @@ -587,17 +588,18 @@ UnownedStringSlice JSONContainer::getTransientString(const JSONValue& in) { switch (in.type) { - case JSONValue::Type::StringRepresentation: + case JSONValue::Type::StringRepresentation: { return StringRepresentation::asSlice(in.stringRep); } - case JSONValue::Type::StringValue: + case JSONValue::Type::StringValue: { return getStringFromKey(in.stringKey); } - case JSONValue::Type::StringLexeme: + case JSONValue::Type::StringLexeme: { - StringEscapeHandler* handler = StringEscapeUtil::getHandler(StringEscapeUtil::Style::JSON); + StringEscapeHandler* handler = + StringEscapeUtil::getHandler(StringEscapeUtil::Style::JSON); UnownedStringSlice lexeme = getLexeme(in); UnownedStringSlice unquoted = StringEscapeUtil::unquote(handler, lexeme); @@ -613,7 +615,7 @@ UnownedStringSlice JSONContainer::getTransientString(const JSONValue& in) return unquoted; } } - case JSONValue::Type::Null: + case JSONValue::Type::Null: { return UnownedStringSlice(); } @@ -625,16 +627,17 @@ UnownedStringSlice JSONContainer::getTransientString(const JSONValue& in) JSONKey JSONContainer::getStringKey(const JSONValue& in) { - return (in.type == JSONValue::Type::StringValue) ? in.stringKey : getKey(getTransientString(in)); + return (in.type == JSONValue::Type::StringValue) ? in.stringKey + : getKey(getTransientString(in)); } - + bool JSONContainer::asBool(const JSONValue& value) { switch (value.type) { - case JSONValue::Type::IntegerLexeme: return asInteger(value) != 0; - case JSONValue::Type::FloatLexeme: return asFloat(value) != 0.0; - default: return value.asBool(); + case JSONValue::Type::IntegerLexeme: return asInteger(value) != 0; + case JSONValue::Type::FloatLexeme: return asFloat(value) != 0.0; + default: return value.asBool(); } } @@ -643,26 +646,26 @@ JSONValue JSONContainer::asValue(const JSONValue& inValue) JSONValue value = inValue; switch (value.type) { - case JSONValue::Type::StringLexeme: + case JSONValue::Type::StringLexeme: { const UnownedStringSlice slice = getTransientString(inValue); value.stringKey = getKey(slice); value.type = JSONValue::Type::StringValue; break; } - case JSONValue::Type::IntegerLexeme: + case JSONValue::Type::IntegerLexeme: { value.floatValue = value.asFloat(); value.type = JSONValue::Type::IntegerValue; break; } - case JSONValue::Type::FloatLexeme: + case JSONValue::Type::FloatLexeme: { value.floatValue = value.asFloat(); value.type = JSONValue::Type::FloatValue; break; } - default: break; + default: break; } return value; @@ -687,12 +690,14 @@ void JSONContainer::clearSourceManagerDependency(JSONValue* ioValues, Index valu { switch (range.type) { - case Range::Type::Array: + case Range::Type::Array: { - _clearSourceManagerDependency(m_arrayValues.getBuffer() + range.startIndex, range.count); + _clearSourceManagerDependency( + m_arrayValues.getBuffer() + range.startIndex, + range.count); break; } - case Range::Type::Object: + case Range::Type::Object: { const Index count = range.count; auto pairs = m_objectValues.getBuffer() + range.startIndex; @@ -706,7 +711,7 @@ void JSONContainer::clearSourceManagerDependency(JSONValue* ioValues, Index valu } break; } - default: break; + default: break; } } @@ -718,7 +723,7 @@ int64_t JSONContainer::asInteger(const JSONValue& value) { switch (value.type) { - case JSONValue::Type::IntegerLexeme: + case JSONValue::Type::IntegerLexeme: { UnownedStringSlice slice = getLexeme(value); int64_t intValue; @@ -729,8 +734,8 @@ int64_t JSONContainer::asInteger(const JSONValue& value) SLANG_ASSERT(!"Couldn't convert int"); return 0; } - case JSONValue::Type::FloatLexeme: return int64_t(asFloat(value)); - default: return value.asInteger(); + case JSONValue::Type::FloatLexeme: return int64_t(asFloat(value)); + default: return value.asInteger(); } } @@ -738,8 +743,8 @@ double JSONContainer::asFloat(const JSONValue& value) { switch (value.type) { - case JSONValue::Type::IntegerLexeme: return double(asInteger(value)); - case JSONValue::Type::FloatLexeme: + case JSONValue::Type::IntegerLexeme: return double(asInteger(value)); + case JSONValue::Type::FloatLexeme: { UnownedStringSlice slice = getLexeme(value); double floatValue; @@ -750,20 +755,22 @@ double JSONContainer::asFloat(const JSONValue& value) SLANG_ASSERT(!"Couldn't convert double"); return 0.0; } - default: return value.asFloat(); + default: return value.asFloat(); } } Index JSONContainer::findObjectIndex(const JSONValue& obj, JSONKey key) const { auto pairs = getObject(obj); - return pairs.findFirstIndex([key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); + return pairs.findFirstIndex( + [key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); } JSONValue JSONContainer::findObjectValue(const JSONValue& obj, JSONKey key) const { auto pairs = getObject(obj); - const Index index = pairs.findFirstIndex([key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); + const Index index = + pairs.findFirstIndex([key](const JSONKeyValue& pair) -> bool { return pair.key == key; }); return (index >= 0) ? pairs[index].value : JSONValue::makeInvalid(); } @@ -787,7 +794,6 @@ void JSONContainer::addToArray(JSONValue& array, const JSONValue& value) // We can just add to the end array.rangeIndex = _addRange(Range::Type::Array, m_arrayValues.getCount(), 1); m_arrayValues.add(value); - } else { @@ -837,7 +843,10 @@ void JSONContainer::_removeKey(JSONValue& obj, Index globalIndex) if (localIndex < range.count - 1) { auto localBuf = m_objectValues.getBuffer() + range.startIndex; - ::memmove(localBuf + localIndex, localBuf + localIndex + 1, sizeof(*localBuf) * (range.count - (localIndex + 1))); + ::memmove( + localBuf + localIndex, + localBuf + localIndex + 1, + sizeof(*localBuf) * (range.count - (localIndex + 1))); } --range.count; @@ -865,8 +874,8 @@ bool JSONContainer::removeKey(JSONValue& obj, const UnownedStringSlice& slice) return false; } -template -/* static */void JSONContainer::_add(Range& ioRange, List& ioList, const T& value) +template +/* static */ void JSONContainer::_add(Range& ioRange, List& ioList, const T& value) { // If we have capacity, we can add to the end if (ioRange.count < ioRange.capacity) @@ -938,7 +947,7 @@ void JSONContainer::_destroyRange(Index rangeIndex) // If the range is at the end, shrink it switch (range.type) { - case Range::Type::Array: + case Range::Type::Array: { if (range.startIndex + range.capacity == m_arrayValues.getCount()) { @@ -946,7 +955,7 @@ void JSONContainer::_destroyRange(Index rangeIndex) } break; } - case Range::Type::Object: + case Range::Type::Object: { if (range.startIndex + range.capacity == m_objectValues.getCount()) { @@ -954,7 +963,7 @@ void JSONContainer::_destroyRange(Index rangeIndex) } break; } - default: break; + default: break; } range.type = Range::Type::Destroyed; @@ -971,7 +980,7 @@ void JSONContainer::destroy(JSONValue& value) } void JSONContainer::destroyRecursively(JSONValue& inValue) -{ +{ if (!(inValue.needsDestroy() && m_ranges[inValue.rangeIndex].isActive())) { inValue.type = JSONValue::Type::Invalid; @@ -1000,7 +1009,7 @@ void JSONContainer::destroyRecursively(JSONValue& inValue) for (Index i = 0; i < count; ++i) { auto& value = buf[i]; - // If we have an active range, add to work list, and destroy + // If we have an active range, add to work list, and destroy if (value.needsDestroy() && m_ranges[value.rangeIndex].isActive()) { activeRanges.add(m_ranges[value.rangeIndex]); @@ -1009,7 +1018,7 @@ void JSONContainer::destroyRecursively(JSONValue& inValue) value.type = JSONValue::Type::Invalid; } } - else + else { SLANG_ASSERT(type == Range::Type::Object); @@ -1019,7 +1028,8 @@ void JSONContainer::destroyRecursively(JSONValue& inValue) { auto& keyValue = buf[i]; auto& value = keyValue.value; - // We want to mark that it's in the list so that if we have a badly formed tree we don't read + // We want to mark that it's in the list so that if we have a badly formed tree we + // don't read if (value.needsDestroy() && m_ranges[value.rangeIndex].isActive()) { activeRanges.add(m_ranges[value.rangeIndex]); @@ -1045,7 +1055,10 @@ bool JSONContainer::areEqual(const JSONValue* a, const JSONValue* b, Index count } -/* static */bool JSONContainer::_sameKeyOrder(const JSONKeyValue* a, const JSONKeyValue* b, Index count) +/* static */ bool JSONContainer::_sameKeyOrder( + const JSONKeyValue* a, + const JSONKeyValue* b, + Index count) { for (Index i = 0; i < count; ++i) { @@ -1064,8 +1077,7 @@ bool JSONContainer::_areEqualOrderedKeys(const JSONKeyValue* a, const JSONKeyVal const auto& curA = a[i]; const auto& curB = b[i]; - if (curA.key != curB.key || - !areEqual(curA.value, curB.value)) + if (curA.key != curB.key || !areEqual(curA.value, curB.value)) { return false; } @@ -1102,15 +1114,17 @@ bool JSONContainer::areEqual(const JSONKeyValue* a, const JSONKeyValue* b, Index } else { - // We need to compare with keys in the same order + // We need to compare with keys in the same order List sortedAs; sortedAs.addRange(a, count); List sortedBs; sortedBs.addRange(b, count); - sortedAs.sort([](const JSONKeyValue&a, const JSONKeyValue& b) -> bool { return a.key < b.key; }); - sortedBs.sort([](const JSONKeyValue&a, const JSONKeyValue& b) -> bool { return a.key < b.key; }); + sortedAs.sort( + [](const JSONKeyValue& a, const JSONKeyValue& b) -> bool { return a.key < b.key; }); + sortedBs.sort( + [](const JSONKeyValue& a, const JSONKeyValue& b) -> bool { return a.key < b.key; }); return _areEqualOrderedKeys(sortedAs.getBuffer(), sortedBs.getBuffer(), count); } @@ -1132,18 +1146,18 @@ bool JSONContainer::areEqual(const JSONValue& a, const JSONValue& b) { switch (a.type) { - default: - // Invalid are never equal - case JSONValue::Type::Invalid: return false; - case JSONValue::Type::True: - case JSONValue::Type::False: - case JSONValue::Type::Null: + default: + // Invalid are never equal + case JSONValue::Type::Invalid: return false; + case JSONValue::Type::True: + case JSONValue::Type::False: + case JSONValue::Type::Null: { return true; } - case JSONValue::Type::IntegerLexeme:return asInteger(a) == asInteger(b); - case JSONValue::Type::FloatLexeme: return asFloat(a) == asFloat(b); - case JSONValue::Type::StringLexeme: + case JSONValue::Type::IntegerLexeme: return asInteger(a) == asInteger(b); + case JSONValue::Type::FloatLexeme: return asFloat(a) == asFloat(b); + case JSONValue::Type::StringLexeme: { // If the lexemes are equal they are equal UnownedStringSlice lexemeA = getLexeme(a); @@ -1151,15 +1165,15 @@ bool JSONContainer::areEqual(const JSONValue& a, const JSONValue& b) // Else we want to decode the string to be sure if they are equal. return lexemeA == lexemeB || getStringKey(a) == getStringKey(b); } - case JSONValue::Type::IntegerValue: return a.intValue == b.intValue; - case JSONValue::Type::FloatValue: return a.floatValue == b.floatValue; - case JSONValue::Type::StringValue: return a.stringKey == b.stringKey; - case JSONValue::Type::StringRepresentation: + case JSONValue::Type::IntegerValue: return a.intValue == b.intValue; + case JSONValue::Type::FloatValue: return a.floatValue == b.floatValue; + case JSONValue::Type::StringValue: return a.stringKey == b.stringKey; + case JSONValue::Type::StringRepresentation: { - return a.stringRep == b.stringRep || - StringRepresentation::asSlice(a.stringRep) == StringRepresentation::asSlice(b.stringRep); + return a.stringRep == b.stringRep || StringRepresentation::asSlice(a.stringRep) == + StringRepresentation::asSlice(b.stringRep); } - case JSONValue::Type::Array: + case JSONValue::Type::Array: { if (a.rangeIndex == b.rangeIndex) { @@ -1169,9 +1183,10 @@ bool JSONContainer::areEqual(const JSONValue& a, const JSONValue& b) auto arrayB = getArray(b); const Index count = arrayA.getCount(); - return (count == arrayB.getCount()) && areEqual(arrayA.getBuffer(), arrayB.getBuffer(), count); + return (count == arrayB.getCount()) && + areEqual(arrayA.getBuffer(), arrayB.getBuffer(), count); } - case JSONValue::Type::Object: + case JSONValue::Type::Object: { if (a.rangeIndex == b.rangeIndex) { @@ -1181,7 +1196,8 @@ bool JSONContainer::areEqual(const JSONValue& a, const JSONValue& b) const auto bValues = getObject(b); const Index count = aValues.getCount(); - return (count == bValues.getCount()) && areEqual(aValues.getBuffer(), bValues.getBuffer(), count); + return (count == bValues.getCount()) && + areEqual(aValues.getBuffer(), bValues.getBuffer(), count); } } } @@ -1192,10 +1208,10 @@ bool JSONContainer::areEqual(const JSONValue& a, const JSONValue& b) { switch (kind) { - case JSONValue::Kind::String: return getStringKey(a) == getStringKey(b); - case JSONValue::Kind::Integer: return asInteger(a) == asInteger(b); - case JSONValue::Kind::Float: return asFloat(a) == asFloat(b); - default: break; + case JSONValue::Kind::String: return getStringKey(a) == getStringKey(b); + case JSONValue::Kind::Integer: return asInteger(a) == asInteger(b); + case JSONValue::Kind::Float: return asFloat(a) == asFloat(b); + default: break; } } @@ -1207,27 +1223,30 @@ void JSONContainer::traverseRecursively(const JSONValue& value, JSONListener* li typedef JSONValue::Type Type; switch (value.type) - { - case Type::True: return listener->addBoolValue(true, value.loc); - case Type::False: return listener->addBoolValue(false, value.loc); - case Type::Null: return listener->addNullValue(value.loc); - - case Type::StringLexeme: return listener->addLexemeValue(JSONTokenType::StringLiteral, getLexeme(value), value.loc); - case Type::IntegerLexeme: return listener->addLexemeValue(JSONTokenType::IntegerLiteral, getLexeme(value), value.loc); - case Type::FloatLexeme: return listener->addLexemeValue(JSONTokenType::FloatLiteral, getLexeme(value), value.loc); - - case Type::IntegerValue: return listener->addIntegerValue(value.intValue, value.loc); - case Type::FloatValue: return listener->addFloatValue(value.floatValue, value.loc); - case Type::StringValue: + { + case Type::True: return listener->addBoolValue(true, value.loc); + case Type::False: return listener->addBoolValue(false, value.loc); + case Type::Null: return listener->addNullValue(value.loc); + + case Type::StringLexeme: + return listener->addLexemeValue(JSONTokenType::StringLiteral, getLexeme(value), value.loc); + case Type::IntegerLexeme: + return listener->addLexemeValue(JSONTokenType::IntegerLiteral, getLexeme(value), value.loc); + case Type::FloatLexeme: + return listener->addLexemeValue(JSONTokenType::FloatLiteral, getLexeme(value), value.loc); + + case Type::IntegerValue: return listener->addIntegerValue(value.intValue, value.loc); + case Type::FloatValue: return listener->addFloatValue(value.floatValue, value.loc); + case Type::StringValue: { const auto slice = getStringFromKey(value.stringKey); return listener->addStringValue(slice, value.loc); } - case Type::StringRepresentation: + case Type::StringRepresentation: { return listener->addStringValue(getTransientString(value), value.loc); } - case Type::Array: + case Type::Array: { listener->startArray(value.loc); @@ -1241,7 +1260,7 @@ void JSONContainer::traverseRecursively(const JSONValue& value, JSONListener* li listener->endArray(SourceLoc()); break; } - case Type::Object: + case Type::Object: { listener->startObject(value.loc); @@ -1260,7 +1279,7 @@ void JSONContainer::traverseRecursively(const JSONValue& value, JSONListener* li listener->endObject(SourceLoc()); break; } - default: + default: { SLANG_ASSERT(!"Invalid type"); return; @@ -1274,9 +1293,8 @@ void JSONContainer::traverseRecursively(const JSONValue& value, JSONListener* li !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -JSONBuilder::JSONBuilder(JSONContainer* container, Flags flags): - m_container(container), - m_flags(flags) +JSONBuilder::JSONBuilder(JSONContainer* container, Flags flags) + : m_container(container), m_flags(flags) { m_state.m_kind = State::Kind::Root; m_state.m_startIndex = 0; @@ -1308,12 +1326,12 @@ void JSONBuilder::_popState() // Reset the end depending on typpe switch (m_state.m_kind) { - case State::Kind::Array: + case State::Kind::Array: { m_values.setCount(m_state.m_startIndex); break; } - case State::Kind::Object: + case State::Kind::Object: { m_keyValues.setCount(m_state.m_startIndex); break; @@ -1346,18 +1364,18 @@ void JSONBuilder::_add(const JSONValue& value) SLANG_ASSERT(value.isValid()); switch (m_state.m_kind) { - case State::Kind::Root: + case State::Kind::Root: { SLANG_ASSERT(!m_rootValue.isValid()); m_rootValue = value; break; } - case State::Kind::Array: + case State::Kind::Array: { m_values.add(value); break; } - case State::Kind::Object: + case State::Kind::Object: { SLANG_ASSERT(m_state.hasKey()); @@ -1398,7 +1416,10 @@ void JSONBuilder::endObject(SourceLoc loc) SLANG_ASSERT(m_state.m_kind == State::Kind::Object); const Index count = m_keyValues.getCount() - m_state.m_startIndex; - const JSONValue value = m_container->createObject(m_keyValues.getBuffer() + m_state.m_startIndex, count, m_state.m_loc); + const JSONValue value = m_container->createObject( + m_keyValues.getBuffer() + m_state.m_startIndex, + count, + m_state.m_loc); // Pop current state _popState(); @@ -1422,7 +1443,8 @@ void JSONBuilder::endArray(SourceLoc loc) SLANG_ASSERT(m_state.m_kind == State::Kind::Array); const Index count = m_values.getCount() - m_state.m_startIndex; - const JSONValue value = m_container->createArray(m_values.getBuffer() + m_state.m_startIndex, count, m_state.m_loc); + const JSONValue value = + m_container->createArray(m_values.getBuffer() + m_state.m_startIndex, count, m_state.m_loc); // Pop current state _popState(); @@ -1449,11 +1471,11 @@ void JSONBuilder::addLexemeValue(JSONTokenType type, const UnownedStringSlice& v { switch (type) { - case JSONTokenType::True: return _add(JSONValue::makeBool(true, loc)); - case JSONTokenType::False: return _add(JSONValue::makeBool(false, loc)); - case JSONTokenType::Null: return _add(JSONValue::makeNull(loc)); - - case JSONTokenType::IntegerLiteral: + case JSONTokenType::True: return _add(JSONValue::makeBool(true, loc)); + case JSONTokenType::False: return _add(JSONValue::makeBool(false, loc)); + case JSONTokenType::Null: return _add(JSONValue::makeNull(loc)); + + case JSONTokenType::IntegerLiteral: { if (m_flags & Flag::ConvertLexemes) { @@ -1470,7 +1492,7 @@ void JSONBuilder::addLexemeValue(JSONTokenType type, const UnownedStringSlice& v } break; } - case JSONTokenType::FloatLiteral: + case JSONTokenType::FloatLiteral: { if (m_flags & Flag::ConvertLexemes) { @@ -1487,7 +1509,7 @@ void JSONBuilder::addLexemeValue(JSONTokenType type, const UnownedStringSlice& v } break; } - case JSONTokenType::StringLiteral: + case JSONTokenType::StringLiteral: { if (m_flags & Flag::ConvertLexemes) { @@ -1504,7 +1526,7 @@ void JSONBuilder::addLexemeValue(JSONTokenType type, const UnownedStringSlice& v } break; } - default: + default: { SLANG_ASSERT(!"Unhandled type"); } diff --git a/source/compiler-core/slang-json-value.h b/source/compiler-core/slang-json-value.h index 0abe7c9a6..d9b17f1d5 100644 --- a/source/compiler-core/slang-json-value.h +++ b/source/compiler-core/slang-json-value.h @@ -3,15 +3,13 @@ #define SLANG_JSON_VALUE_H #include "../core/slang-basic.h" - -#include "slang-source-loc.h" +#include "../core/slang-rtti-info.h" #include "slang-diagnostic-sink.h" - #include "slang-json-parser.h" +#include "slang-source-loc.h" -#include "../core/slang-rtti-info.h" - -namespace Slang { +namespace Slang +{ typedef uint32_t JSONKey; @@ -31,7 +29,7 @@ struct JSONValue Array, Object, - CountOf, + CountOf, }; enum class Type @@ -58,39 +56,96 @@ struct JSONValue CountOf, }; - static bool isLexeme(Type type) { return Index(type) >= Index(Type::StringLexeme) && Index(type) <= Index(Type::FloatLexeme); } + static bool isLexeme(Type type) + { + return Index(type) >= Index(Type::StringLexeme) && Index(type) <= Index(Type::FloatLexeme); + } - static JSONValue makeInt(int64_t inValue, SourceLoc loc = SourceLoc()) { JSONValue value; value.type = Type::IntegerValue; value.loc = loc; value.intValue = inValue; return value; } - static JSONValue makeFloat(double inValue, SourceLoc loc = SourceLoc()) { JSONValue value; value.type = Type::FloatValue; value.loc = loc; value.floatValue = inValue; return value; } - static JSONValue makeNull(SourceLoc loc = SourceLoc()) { JSONValue value; value.type = Type::Null; value.loc = loc; return value; } - static JSONValue makeBool(bool inValue, SourceLoc loc = SourceLoc()) { JSONValue value; value.type = (inValue ? Type::True : Type::False); value.loc = loc; return value; } + static JSONValue makeInt(int64_t inValue, SourceLoc loc = SourceLoc()) + { + JSONValue value; + value.type = Type::IntegerValue; + value.loc = loc; + value.intValue = inValue; + return value; + } + static JSONValue makeFloat(double inValue, SourceLoc loc = SourceLoc()) + { + JSONValue value; + value.type = Type::FloatValue; + value.loc = loc; + value.floatValue = inValue; + return value; + } + static JSONValue makeNull(SourceLoc loc = SourceLoc()) + { + JSONValue value; + value.type = Type::Null; + value.loc = loc; + return value; + } + static JSONValue makeBool(bool inValue, SourceLoc loc = SourceLoc()) + { + JSONValue value; + value.type = (inValue ? Type::True : Type::False); + value.loc = loc; + return value; + } - static JSONValue makeLexeme(Type type, SourceLoc loc, Index length) { SLANG_ASSERT(isLexeme(type)); JSONValue value; value.type = type; value.loc = loc; value.length = length; return value; } + static JSONValue makeLexeme(Type type, SourceLoc loc, Index length) + { + SLANG_ASSERT(isLexeme(type)); + JSONValue value; + value.type = type; + value.loc = loc; + value.length = length; + return value; + } - static JSONValue makeEmptyArray(SourceLoc loc = SourceLoc()) { JSONValue value; value.type = Type::Array; value.loc = loc; value.rangeIndex = 0; return value; } - static JSONValue makeEmptyObject(SourceLoc loc = SourceLoc()) { JSONValue value; value.type = Type::Object; value.loc = loc; value.rangeIndex = 0; return value; } + static JSONValue makeEmptyArray(SourceLoc loc = SourceLoc()) + { + JSONValue value; + value.type = Type::Array; + value.loc = loc; + value.rangeIndex = 0; + return value; + } + static JSONValue makeEmptyObject(SourceLoc loc = SourceLoc()) + { + JSONValue value; + value.type = Type::Object; + value.loc = loc; + value.rangeIndex = 0; + return value; + } - static JSONValue makeInvalid(SourceLoc loc = SourceLoc()) { JSONValue value; value.type = Type::Invalid; value.loc = loc; return value; } - // The following functions only work if the value is stored directly NOT as a lexeme. Use the methods on the container - // to access values if it is potentially stored as a lexeme + static JSONValue makeInvalid(SourceLoc loc = SourceLoc()) + { + JSONValue value; + value.type = Type::Invalid; + value.loc = loc; + return value; + } + // The following functions only work if the value is stored directly NOT as a lexeme. Use the + // methods on the container to access values if it is potentially stored as a lexeme - /// As a boolean value + /// As a boolean value bool asBool() const; - /// As an integer value + /// As an integer value int64_t asInteger() const; - /// As a float value + /// As a float value double asFloat() const; - /// True if this is a object like + /// True if this is a object like bool isObjectLike() const { return Index(type) >= Index(Type::Array); } - /// True if this appears to be a valid value + /// True if this appears to be a valid value bool isValid() const { return type != JSONValue::Type::Invalid; } - /// True if needs destroy + /// True if needs destroy bool needsDestroy() const { return isObjectLike() && rangeIndex != 0; } - /// Get the kind + /// Get the kind SLANG_FORCE_INLINE Kind getKind() const { return getKindForType(type); } void reset() @@ -99,20 +154,20 @@ struct JSONValue loc = SourceLoc(); } - /// Given a type return the associated kind + /// Given a type return the associated kind static Kind getKindForType(Type type) { return g_typeToKind[Index(type)]; } - Type type = Type::Invalid; ///< The type of value - SourceLoc loc; ///< The (optional) location in source of this value. + Type type = Type::Invalid; ///< The type of value + SourceLoc loc; ///< The (optional) location in source of this value. - union + union { - Index rangeIndex; ///< Used for Array/Object - Index length; ///< Length in bytes if it is a 'Lexeme' - double floatValue; ///< Float value - int64_t intValue; ///< Integer value - JSONKey stringKey; ///< The pool key if it's a string - StringRepresentation* stringRep; ///< Only ever used on a 'PersistentJSONValue' + Index rangeIndex; ///< Used for Array/Object + Index length; ///< Length in bytes if it is a 'Lexeme' + double floatValue; ///< Float value + int64_t intValue; ///< Integer value + JSONKey stringKey; ///< The pool key if it's a string + StringRepresentation* stringRep; ///< Only ever used on a 'PersistentJSONValue' }; static const Kind g_typeToKind[Index(Type::CountOf)]; @@ -120,12 +175,15 @@ struct JSONValue static const OtherRttiInfo g_rttiInfo; }; -template <> -struct GetRttiInfo { static const RttiInfo* get() { return &JSONValue::g_rttiInfo; } }; +template<> +struct GetRttiInfo +{ + static const RttiInfo* get() { return &JSONValue::g_rttiInfo; } +}; struct JSONKeyValue { - /// True if it's valid + /// True if it's valid bool isValid() const { return value.type != JSONValue::Type::Invalid; } void reset() @@ -141,7 +199,7 @@ struct JSONKeyValue static JSONKeyValue make(JSONKey inKey, JSONValue inValue, SourceLoc inKeyLoc = SourceLoc()) { - return JSONKeyValue{ inKey, inKeyLoc, inValue }; + return JSONKeyValue{inKey, inKeyLoc, inValue}; } static JSONKeyValue g_invalid; @@ -168,31 +226,35 @@ public: typedef JSONValue Super; typedef PersistentJSONValue ThisType; - /// If it's a string type this will always work + /// If it's a string type this will always work String getString() const; UnownedStringSlice getSlice() const; - /// Set to the value + /// Set to the value void set(const JSONValue& in, JSONContainer* container); - /// Set directly to a string + /// Set directly to a string void set(const UnownedStringSlice& slice, SourceLoc loc); - /// True if identical + /// True if identical bool operator==(const ThisType& rhs) const; bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - /// Assignable + /// Assignable void operator=(const ThisType& rhs); PersistentJSONValue(const JSONValue& in, JSONContainer* container) { _init(in, container); } - PersistentJSONValue(const JSONValue& in, JSONContainer* container, SourceLoc inLoc) { _init(in, container); loc = inLoc; } + PersistentJSONValue(const JSONValue& in, JSONContainer* container, SourceLoc inLoc) + { + _init(in, container); + loc = inLoc; + } - /// Copy Ctor + /// Copy Ctor PersistentJSONValue(const ThisType& rhs); - /// Default Ctor (will be set to invalid) + /// Default Ctor (will be set to invalid) PersistentJSONValue() {} - + ~PersistentJSONValue() { if (type == Type::StringRepresentation && stringRep) @@ -200,8 +262,9 @@ public: stringRep->releaseReference(); } } + protected: - /// Assumes this has no valid data + /// Assumes this has no valid data void _init(const JSONValue& in, JSONContainer* container); void _init(const UnownedStringSlice& slice, SourceLoc loc); }; @@ -209,13 +272,15 @@ protected: class JSONContainer : public RefObject { public: - - /// Make a new array + /// Make a new array JSONValue createArray(const JSONValue* values, Index valuesCount, SourceLoc loc = SourceLoc()); - /// Make a new object - JSONValue createObject(const JSONKeyValue* keyValues, Index keyValueCount, SourceLoc loc = SourceLoc()); - /// Make a string - JSONValue createString(const UnownedStringSlice& slice, SourceLoc loc = SourceLoc()); + /// Make a new object + JSONValue createObject( + const JSONKeyValue* keyValues, + Index keyValueCount, + SourceLoc loc = SourceLoc()); + /// Make a string + JSONValue createString(const UnownedStringSlice& slice, SourceLoc loc = SourceLoc()); ConstArrayView getArray(const JSONValue& in) const; ConstArrayView getObject(const JSONValue& in) const; @@ -223,104 +288,111 @@ public: ArrayView getArray(const JSONValue& in); ArrayView getObject(const JSONValue& in); - /// Add value to array. + /// Add value to array. void addToArray(JSONValue& array, const JSONValue& value); - /// Get the value at the index in the array + /// Get the value at the index in the array JSONValue& getAt(const JSONValue& array, Index index); - /// Returns the index of key in obj, or -1 if not found + /// Returns the index of key in obj, or -1 if not found Index findObjectIndex(const JSONValue& obj, JSONKey key) const; - /// Get the value in the object at key. Returns invalid if not found. + /// Get the value in the object at key. Returns invalid if not found. JSONValue findObjectValue(const JSONValue& obj, JSONKey key) const; - /// Returns the index + /// Returns the index Index findKeyGlobalIndex(const JSONValue& obj, JSONKey key); Index findKeyGlobalIndex(const JSONValue& obj, const UnownedStringSlice& slice); - /// Set a key value for the obj - void setKeyValue(JSONValue& obj, JSONKey key, const JSONValue& value, SourceLoc loc = SourceLoc()); + /// Set a key value for the obj + void setKeyValue( + JSONValue& obj, + JSONKey key, + const JSONValue& value, + SourceLoc loc = SourceLoc()); - /// Returns true if found + /// Returns true if found bool removeKey(JSONValue& obj, JSONKey key); bool removeKey(JSONValue& obj, const UnownedStringSlice& slice); - /// As a boolean value + /// As a boolean value bool asBool(const JSONValue& value); - /// As an integer value + /// As an integer value int64_t asInteger(const JSONValue& value); - /// As a float value + /// As a float value double asFloat(const JSONValue& value); - /// Returns string as a key + /// Returns string as a key JSONKey getStringKey(const JSONValue& in); - /// Get as a string. The slice may used backing lexeme (ie will only last - /// as long as the backing JSON text, or be decoded and be transitory). + /// Get as a string. The slice may used backing lexeme (ie will only last + /// as long as the backing JSON text, or be decoded and be transitory). UnownedStringSlice getTransientString(const JSONValue& in); - /// Get as a string. The contents will stay in scope as long as the container + /// Get as a string. The contents will stay in scope as long as the container UnownedStringSlice getString(const JSONValue& in); - /// Gets the lexeme + /// Gets the lexeme UnownedStringSlice getLexeme(const JSONValue& in); - /// Get a key for a name + /// Get a key for a name JSONKey getKey(const UnownedStringSlice& slice); - /// Returns JSONKey(0) if not found + /// Returns JSONKey(0) if not found JSONKey findKey(const UnownedStringSlice& slice) const; - /// Get the string from the key - UnownedStringSlice getStringFromKey(JSONKey key) const { return m_slicePool.getSlice(StringSlicePool::Handle(key)); } + /// Get the string from the key + UnownedStringSlice getStringFromKey(JSONKey key) const + { + return m_slicePool.getSlice(StringSlicePool::Handle(key)); + } - /// True if they are the same value - /// If object like type comparison is performed recursively. - /// NOTE! That Float and Integer values do not compare & source locations are ignored. + /// True if they are the same value + /// If object like type comparison is performed recursively. + /// NOTE! That Float and Integer values do not compare & source locations are ignored. bool areEqual(const JSONValue& a, const JSONValue& b); bool areEqual(const JSONValue* a, const JSONValue* b, Index count); bool areEqual(const JSONKeyValue* a, const JSONKeyValue* b, Index count); bool areEqual(const JSONValue& a, const UnownedStringSlice& slice); - /// Destroy value + /// Destroy value void destroy(JSONValue& value); - /// Destroy recursively from value + /// Destroy recursively from value void destroyRecursively(JSONValue& value); - /// Traverse a JSON hierarchy from value, outputting to the listener + /// Traverse a JSON hierarchy from value, outputting to the listener void traverseRecursively(const JSONValue& value, JSONListener* listener); - /// Returns the source manager used. - SourceManager* getSourceManager() const { return m_sourceManager; } - /// Set the source manager - void setSourceManager(SourceManager* sourceManger) { m_sourceManager = sourceManger; } + /// Returns the source manager used. + SourceManager* getSourceManager() const { return m_sourceManager; } + /// Set the source manager + void setSourceManager(SourceManager* sourceManger) { m_sourceManager = sourceManger; } - /// Clears all the source locs. Useful if the sourceManager is no longer available, or has itself been reset. - /// All JSONValues which were Lexeme based will become held in the container - /// The source manager will set to nullptr + /// Clears all the source locs. Useful if the sourceManager is no longer available, or has + /// itself been reset. All JSONValues which were Lexeme based will become held in the container + /// The source manager will set to nullptr void clearSourceManagerDependency(JSONValue* ioValues, Index count); - /// Reset the state + /// Reset the state void reset(); - /// Return inValue as a regular value (ie not held as a lexeme) + /// Return inValue as a regular value (ie not held as a lexeme) JSONValue asValue(const JSONValue& inValue); - // Ctor + // Ctor JSONContainer(SourceManager* sourceManger); - /// Returns true if all the keys are unique + /// Returns true if all the keys are unique static bool areKeysUnique(const JSONKeyValue* keyValues, Index keyValueCount); - /// Access the internal set of strings, removing anything from this - /// will invalidate the container, so only do it immediately prior to - /// destruction. - StringSlicePool& getStringSlicePool() {return m_slicePool;}; + /// Access the internal set of strings, removing anything from this + /// will invalidate the container, so only do it immediately prior to + /// destruction. + StringSlicePool& getStringSlicePool() { return m_slicePool; }; protected: struct Range { - // We want to record the underlying range, because we don't track JSONValue, and so we need to know what the range - // applies to if we want to reorder, flatten etc. + // We want to record the underlying range, because we don't track JSONValue, and so we need + // to know what the range applies to if we want to reorder, flatten etc. enum class Type { None, @@ -329,7 +401,7 @@ protected: Array, }; - /// Is active if it consuming some part of a value list (even if zero count) + /// Is active if it consuming some part of a value list (even if zero count) SLANG_FORCE_INLINE bool isActive() const { return Index(type) >= Index(Type::Object); } Type type; @@ -338,24 +410,24 @@ protected: Index capacity; }; - template + template static void _add(Range& range, List& list, const T& value); Index _addRange(Range::Type type, Index startIndex, Index count); void _removeKey(JSONValue& obj, Index globalIndex); - /// Note does not destroy values in range. + /// Note does not destroy values in range. void _destroyRange(Index rangeIndex); static bool _sameKeyOrder(const JSONKeyValue* a, const JSONKeyValue* b, Index count); - /// True if the values are equal + /// True if the values are equal bool _areEqualValues(const JSONKeyValue* a, const JSONKeyValue* b, Index count); - /// True if the key and value are equal + /// True if the key and value are equal bool _areEqualOrderedKeys(const JSONKeyValue* a, const JSONKeyValue* b, Index count); void _clearSourceManagerDependency(JSONValue* ioValues, Index count); JSONValue _removeManagerDependency(const JSONValue& inValue); - StringBuilder m_buf; ///< A temporary buffer used to hold unescaped strings + StringBuilder m_buf; ///< A temporary buffer used to hold unescaped strings SourceView* m_currentView = nullptr; SourceManager* m_sourceManager; @@ -370,7 +442,6 @@ protected: class JSONBuilder : public JSONListener { public: - typedef uint32_t Flags; struct Flag { @@ -387,23 +458,23 @@ public: virtual void endArray(SourceLoc loc) SLANG_OVERRIDE; virtual void addQuotedKey(const UnownedStringSlice& key, SourceLoc loc) SLANG_OVERRIDE; virtual void addUnquotedKey(const UnownedStringSlice& key, SourceLoc loc) SLANG_OVERRIDE; - virtual void addLexemeValue(JSONTokenType type, const UnownedStringSlice& value, SourceLoc loc) SLANG_OVERRIDE; + virtual void addLexemeValue(JSONTokenType type, const UnownedStringSlice& value, SourceLoc loc) + SLANG_OVERRIDE; virtual void addIntegerValue(int64_t value, SourceLoc loc) SLANG_OVERRIDE; virtual void addFloatValue(double value, SourceLoc loc) SLANG_OVERRIDE; virtual void addBoolValue(bool value, SourceLoc loc) SLANG_OVERRIDE; virtual void addStringValue(const UnownedStringSlice& string, SourceLoc loc) SLANG_OVERRIDE; virtual void addNullValue(SourceLoc loc) SLANG_OVERRIDE; - /// Reset the state + /// Reset the state void reset(); - /// Get the root value. Will be set after valid construction + /// Get the root value. Will be set after valid construction const JSONValue& getRootValue() const { return m_rootValue; } JSONBuilder(JSONContainer* container, Flags flags = 0); protected: - struct State { enum class Kind : uint8_t @@ -412,8 +483,16 @@ protected: Object, Array, }; - void setKey(JSONKey key, SourceLoc loc) { m_key = key; m_keyLoc = loc; } - void resetKey() { m_key = JSONKey(0); m_keyLoc = SourceLoc(); } + void setKey(JSONKey key, SourceLoc loc) + { + m_key = key; + m_keyLoc = loc; + } + void resetKey() + { + m_key = JSONKey(0); + m_keyLoc = SourceLoc(); + } bool hasKey() const { return m_key != JSONKey(0); } Kind m_kind; diff --git a/source/compiler-core/slang-language-server-protocol.cpp b/source/compiler-core/slang-language-server-protocol.cpp index 93ea0c9e3..9a382e756 100644 --- a/source/compiler-core/slang-language-server-protocol.cpp +++ b/source/compiler-core/slang-language-server-protocol.cpp @@ -38,18 +38,25 @@ const StructRttiInfo InlayHintOptions::g_rttiInfo = _makeInlayHintOptionsRtti(); static const StructRttiInfo _makeDocumentOnTypeFormattingOptionsRtti() { DocumentOnTypeFormattingOptions obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::DocumentOnTypeFormattingOptions", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::DocumentOnTypeFormattingOptions", + nullptr); builder.addField("firstTriggerCharacter", &obj.firstTriggerCharacter); builder.addField("moreTriggerCharacter", &obj.moreTriggerCharacter); builder.ignoreUnknownFields(); return builder.make(); } -const StructRttiInfo DocumentOnTypeFormattingOptions::g_rttiInfo = _makeDocumentOnTypeFormattingOptionsRtti(); +const StructRttiInfo DocumentOnTypeFormattingOptions::g_rttiInfo = + _makeDocumentOnTypeFormattingOptionsRtti(); static const StructRttiInfo _makeCompletionOptionsRtti() { CompletionOptions obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::CompletionOptions", &WorkDoneProgressParams::g_rttiInfo); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::CompletionOptions", + &WorkDoneProgressParams::g_rttiInfo); builder.addField("triggerCharacters", &obj.triggerCharacters); builder.addField("resolveProvider", &obj.resolveProvider); builder.addField("allCommitCharacters", &obj.allCommitCharacters); @@ -118,7 +125,10 @@ const StructRttiInfo TextDocumentIdentifier::g_rttiInfo = _makeTextDocumentIdent static const StructRttiInfo _makeVersionedTextDocumentIdentifierRtti() { VersionedTextDocumentIdentifier obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::VersionedTextDocumentIdentifier", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::VersionedTextDocumentIdentifier", + nullptr); builder.addField("uri", &obj.uri); builder.addField("version", &obj.version); builder.ignoreUnknownFields(); @@ -130,8 +140,7 @@ const StructRttiInfo VersionedTextDocumentIdentifier::g_rttiInfo = static const StructRttiInfo _makePositionRtti() { Position obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::Position", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::Position", nullptr); builder.addField("line", &obj.line); builder.addField("character", &obj.character); builder.ignoreUnknownFields(); @@ -176,7 +185,10 @@ const UnownedStringSlice DidOpenTextDocumentParams::methodName = static const StructRttiInfo _makeTextDocumentContentChangeEventRtti() { TextDocumentContentChangeEvent obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::TextDocumentContentChangeEvent", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::TextDocumentContentChangeEvent", + nullptr); builder.addField("range", &obj.range, StructRttiInfo::Flag::Optional); builder.addField("text", &obj.text); builder.ignoreUnknownFields(); @@ -188,8 +200,7 @@ const StructRttiInfo TextDocumentContentChangeEvent::g_rttiInfo = static const StructRttiInfo _makeDidChangeTextDocumentParamsRtti() { DidChangeTextDocumentParams obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::DidChangeTextDocumentParams", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::DidChangeTextDocumentParams", nullptr); builder.addField("textDocument", &obj.textDocument); builder.addField("contentChanges", &obj.contentChanges); builder.ignoreUnknownFields(); @@ -216,7 +227,10 @@ const UnownedStringSlice DidCloseTextDocumentParams::methodName = static const StructRttiInfo _makeWorkspaceFoldersServerCapabilitiesRtti() { WorkspaceFoldersServerCapabilities obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::WorkspaceFoldersServerCapabilities", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::WorkspaceFoldersServerCapabilities", + nullptr); builder.addField("supported", &obj.supported); builder.addField("changeNotifications", &obj.changeNotifications); builder.ignoreUnknownFields(); @@ -370,7 +384,10 @@ const StructRttiInfo Location::g_rttiInfo = _makeLocationRtti(); static const StructRttiInfo _makeDiagnosticRelatedInformationRtti() { DiagnosticRelatedInformation obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::DiagnosticRelatedInformation", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::DiagnosticRelatedInformation", + nullptr); builder.addField("location", &obj.location); builder.addField("message", &obj.message); builder.ignoreUnknownFields(); @@ -382,8 +399,7 @@ const StructRttiInfo DiagnosticRelatedInformation::g_rttiInfo = static const StructRttiInfo _makeDiagnosticRtti() { Diagnostic obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::Diagnostic", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::Diagnostic", nullptr); builder.addField("code", &obj.code); builder.addField("message", &obj.message); builder.addField("range", &obj.range); @@ -420,7 +436,10 @@ const StructRttiInfo TextDocumentPositionParams::g_rttiInfo = _makeTextDocumentP static const StructRttiInfo _makeHoverParamsRtti() { HoverParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::HoverParams", &WorkDoneProgressParams::g_rttiInfo); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::HoverParams", + &WorkDoneProgressParams::g_rttiInfo); builder.addField("textDocument", &obj.textDocument); builder.addField("position", &obj.position); builder.ignoreUnknownFields(); @@ -466,7 +485,10 @@ const StructRttiInfo CompletionContext::g_rttiInfo = _makeCompletionContextRtti( static const StructRttiInfo _makeDefinitionParamsRtti() { DefinitionParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::DefinitionParams", &WorkDoneProgressParams::g_rttiInfo); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::DefinitionParams", + &WorkDoneProgressParams::g_rttiInfo); builder.addField("textDocument", &obj.textDocument); builder.addField("position", &obj.position); builder.ignoreUnknownFields(); @@ -479,7 +501,10 @@ const UnownedStringSlice DefinitionParams::methodName = static const StructRttiInfo _makeCompletionParamsRtti() { CompletionParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::CompletionParams", &WorkDoneProgressParams::g_rttiInfo); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::CompletionParams", + &WorkDoneProgressParams::g_rttiInfo); builder.addField("textDocument", &obj.textDocument); builder.addField("position", &obj.position); builder.addField("context", &obj.context, StructRttiInfo::Flag::Optional); @@ -524,7 +549,10 @@ const StructRttiInfo TextEditCompletionItem::g_rttiInfo = _makeTextEditCompletio static const StructRttiInfo _makeSemanticTokensParamsRtti() { SemanticTokensParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::SemanticTokensParams", &WorkDoneProgressParams::g_rttiInfo); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::SemanticTokensParams", + &WorkDoneProgressParams::g_rttiInfo); builder.addField("textDocument", &obj.textDocument); builder.ignoreUnknownFields(); return builder.make(); @@ -547,7 +575,10 @@ const StructRttiInfo SemanticTokens::g_rttiInfo = _makeSemanticTokensRtti(); static const StructRttiInfo _makeSignatureHelpParamsRtti() { SignatureHelpParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::SignatureHelpParams", &WorkDoneProgressParams::g_rttiInfo); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::SignatureHelpParams", + &WorkDoneProgressParams::g_rttiInfo); builder.addField("textDocument", &obj.textDocument); builder.addField("position", &obj.position); builder.ignoreUnknownFields(); @@ -595,7 +626,10 @@ const StructRttiInfo SignatureHelp::g_rttiInfo = _makeSignatureHelpRtti(); static const StructRttiInfo _makeDidChangeConfigurationParamsRtti() { DidChangeConfigurationParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::DidChangeConfigurationParams", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::DidChangeConfigurationParams", + nullptr); builder.addField("settings", &obj.settings, StructRttiInfo::Flag::Optional); builder.ignoreUnknownFields(); return builder.make(); @@ -608,8 +642,7 @@ const UnownedStringSlice DidChangeConfigurationParams::methodName = static const StructRttiInfo _makeConfigurationItemRtti() { ConfigurationItem obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::ConfigurationItem", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::ConfigurationItem", nullptr); builder.addField("section", &obj.section, StructRttiInfo::Flag::Optional); builder.ignoreUnknownFields(); return builder.make(); @@ -619,8 +652,7 @@ const StructRttiInfo ConfigurationItem::g_rttiInfo = _makeConfigurationItemRtti( static const StructRttiInfo _makeConfigurationParamsRtti() { ConfigurationParams obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::ConfigurationParams", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::ConfigurationParams", nullptr); builder.addField("items", &obj.items, StructRttiInfo::Flag::Optional); builder.ignoreUnknownFields(); return builder.make(); @@ -677,7 +709,9 @@ static const StructRttiInfo _makeDocumentSymbolParamsRtti() { DocumentSymbolParams obj; StructRttiBuilder builder( - &obj, "LanguageServerProtocol::DocumentSymbolParams", &WorkDoneProgressParams::g_rttiInfo); + &obj, + "LanguageServerProtocol::DocumentSymbolParams", + &WorkDoneProgressParams::g_rttiInfo); builder.addField("textDocument", &obj.textDocument); builder.ignoreUnknownFields(); return builder.make(); @@ -689,8 +723,7 @@ const UnownedStringSlice DocumentSymbolParams::methodName = static const StructRttiInfo _makeDocumentSymbolRtti() { DocumentSymbol obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::DocumentSymbol", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::DocumentSymbol", nullptr); builder.addField("name", &obj.name); builder.addField("detail", &obj.detail); builder.addField("kind", &obj.kind); @@ -705,8 +738,7 @@ const StructRttiInfo DocumentSymbol::g_rttiInfo = _makeDocumentSymbolRtti(); static const StructRttiInfo _makeInlayHintParamsRtti() { InlayHintParams obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::InlayHintParams", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::InlayHintParams", nullptr); builder.addField("range", &obj.range); builder.addField("textDocument", &obj.textDocument); builder.ignoreUnknownFields(); @@ -719,8 +751,7 @@ const UnownedStringSlice InlayHintParams::methodName = static const StructRttiInfo _makeInlayHintRtti() { InlayHint obj; - StructRttiBuilder builder( - &obj, "LanguageServerProtocol::InlayHint", nullptr); + StructRttiBuilder builder(&obj, "LanguageServerProtocol::InlayHint", nullptr); builder.addField("position", &obj.position); builder.addField("label", &obj.label); builder.addField("kind", &obj.kind); @@ -748,30 +779,38 @@ const UnownedStringSlice DocumentFormattingParams::methodName = static const StructRttiInfo _makeDocumentRangeFormattingParamsRtti() { DocumentRangeFormattingParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::DocumentRangeFormattingParams", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::DocumentRangeFormattingParams", + nullptr); builder.addField("textDocument", &obj.textDocument); builder.addField("range", &obj.range); builder.ignoreUnknownFields(); return builder.make(); } -const StructRttiInfo DocumentRangeFormattingParams::g_rttiInfo = _makeDocumentRangeFormattingParamsRtti(); +const StructRttiInfo DocumentRangeFormattingParams::g_rttiInfo = + _makeDocumentRangeFormattingParamsRtti(); const UnownedStringSlice DocumentRangeFormattingParams::methodName = UnownedStringSlice::fromLiteral("textDocument/rangeFormatting"); static const StructRttiInfo _makeDocumentOnTypeFormattingParamsRtti() { DocumentOnTypeFormattingParams obj; - StructRttiBuilder builder(&obj, "LanguageServerProtocol::DocumentOnTypeFormattingParams", nullptr); + StructRttiBuilder builder( + &obj, + "LanguageServerProtocol::DocumentOnTypeFormattingParams", + nullptr); builder.addField("textDocument", &obj.textDocument); builder.addField("position", &obj.position); builder.addField("ch", &obj.ch); builder.ignoreUnknownFields(); return builder.make(); } -const StructRttiInfo DocumentOnTypeFormattingParams::g_rttiInfo = _makeDocumentOnTypeFormattingParamsRtti(); +const StructRttiInfo DocumentOnTypeFormattingParams::g_rttiInfo = + _makeDocumentOnTypeFormattingParamsRtti(); const UnownedStringSlice DocumentOnTypeFormattingParams::methodName = UnownedStringSlice::fromLiteral("textDocument/onTypeFormatting"); } // namespace LanguageServerProtocol -} +} // namespace Slang diff --git a/source/compiler-core/slang-language-server-protocol.h b/source/compiler-core/slang-language-server-protocol.h index 506969dcc..d96099da6 100644 --- a/source/compiler-core/slang-language-server-protocol.h +++ b/source/compiler-core/slang-language-server-protocol.h @@ -1,11 +1,11 @@ #pragma once +#include "../../source/compiler-core/slang-json-value.h" +#include "../../source/core/slang-rtti-info.h" #include "slang-com-helper.h" #include "slang-com-ptr.h" #include "slang.h" -#include "../../source/core/slang-rtti-info.h" -#include "../../source/compiler-core/slang-json-value.h" #include namespace Slang @@ -192,7 +192,6 @@ struct TextEdit String newText; static const StructRttiInfo g_rttiInfo; - }; struct DidOpenTextDocumentParams @@ -264,7 +263,6 @@ struct InlayHintOptions */ bool resolveProvider = false; static const StructRttiInfo g_rttiInfo; - }; struct DocumentOnTypeFormattingOptions @@ -436,8 +434,7 @@ struct Diagnostic HashCode getHashCode() const { - return combineHash( - code, combineHash(range.start.line, message.getHashCode())); + return combineHash(code, combineHash(range.start.line, message.getHashCode())); } static const StructRttiInfo g_rttiInfo; @@ -473,17 +470,13 @@ struct TextDocumentPositionParams static const StructRttiInfo g_rttiInfo; }; -struct HoverParams - : WorkDoneProgressParams - ,TextDocumentPositionParams +struct HoverParams : WorkDoneProgressParams, TextDocumentPositionParams { static const StructRttiInfo g_rttiInfo; static const UnownedStringSlice methodName; }; -struct DefinitionParams - : WorkDoneProgressParams - , TextDocumentPositionParams +struct DefinitionParams : WorkDoneProgressParams, TextDocumentPositionParams { static const StructRttiInfo g_rttiInfo; static const UnownedStringSlice methodName; @@ -556,9 +549,7 @@ struct CompletionContext static const StructRttiInfo g_rttiInfo; }; -struct CompletionParams - : WorkDoneProgressParams - , TextDocumentPositionParams +struct CompletionParams : WorkDoneProgressParams, TextDocumentPositionParams { CompletionContext context; @@ -713,9 +704,7 @@ struct SemanticTokens static const StructRttiInfo g_rttiInfo; }; -struct SignatureHelpParams - : WorkDoneProgressParams - , TextDocumentPositionParams +struct SignatureHelpParams : WorkDoneProgressParams, TextDocumentPositionParams { static const UnownedStringSlice methodName; @@ -740,7 +729,7 @@ struct ParameterInformation * signature label. Its intended use case is to highlight the parameter * label part in the `SignatureInformation.label`. */ - uint32_t label[2] = { 0, 0 }; + uint32_t label[2] = {0, 0}; /** * The human-readable doc-comment of this parameter. Will be shown @@ -848,14 +837,14 @@ struct ConfigurationParams struct Registration { /** - * The id used to register the request. The id can be used to deregister - * the request again. - */ + * The id used to register the request. The id can be used to deregister + * the request again. + */ String id; /** - * The method / capability to register for. - */ + * The method / capability to register for. + */ String method; static const StructRttiInfo g_rttiInfo; @@ -1052,7 +1041,6 @@ struct InlayHint bool paddingRight = false; static const StructRttiInfo g_rttiInfo; - }; struct DocumentOnTypeFormattingParams @@ -1080,7 +1068,7 @@ struct DocumentOnTypeFormattingParams /** * The formatting options. */ - //FormattingOptions options; + // FormattingOptions options; static const StructRttiInfo g_rttiInfo; static const UnownedStringSlice methodName; @@ -1101,7 +1089,7 @@ struct DocumentRangeFormattingParams /** * The format options */ - //FormattingOptions options; + // FormattingOptions options; static const StructRttiInfo g_rttiInfo; static const UnownedStringSlice methodName; @@ -1117,7 +1105,7 @@ struct DocumentFormattingParams /** * The format options */ - //FormattingOptions options; + // FormattingOptions options; static const StructRttiInfo g_rttiInfo; static const UnownedStringSlice methodName; @@ -1128,29 +1116,20 @@ struct DocumentFormattingParams namespace Slang { - template - struct LanguageServerResult +template +struct LanguageServerResult +{ + SlangResult returnCode; + bool isNull = true; + T result; + LanguageServerResult() { returnCode = SLANG_OK; } + LanguageServerResult(std::nullopt_t) { returnCode = SLANG_OK; } + LanguageServerResult(const T& value) { - SlangResult returnCode; - bool isNull = true; - T result; - LanguageServerResult() - { - returnCode = SLANG_OK; - } - LanguageServerResult(std::nullopt_t) - { - returnCode = SLANG_OK; - } - LanguageServerResult(const T& value) - { - result = value; - isNull = false; - returnCode = SLANG_OK; - } - LanguageServerResult(SlangResult code) - { - returnCode = code; - } - }; -} + result = value; + isNull = false; + returnCode = SLANG_OK; + } + LanguageServerResult(SlangResult code) { returnCode = code; } +}; +} // namespace Slang diff --git a/source/compiler-core/slang-lexer-diagnostic-defs.h b/source/compiler-core/slang-lexer-diagnostic-defs.h index bce287685..cae8e4157 100644 --- a/source/compiler-core/slang-lexer-diagnostic-defs.h +++ b/source/compiler-core/slang-lexer-diagnostic-defs.h @@ -12,7 +12,7 @@ // for any arguments. #ifndef DIAGNOSTIC -#error Need to #define DIAGNOSTIC(...) before including +#error Need to #define DIAGNOSTIC(...) before including #define DIAGNOSTIC(id, severity, name, messageFormat) /* */ #endif @@ -29,7 +29,11 @@ DIAGNOSTIC(10003, Error, invalidDigitForBase, "invalid digit for base-$1 literal DIAGNOSTIC(10004, Error, endOfFileInLiteral, "end of file in literal") DIAGNOSTIC(10005, Error, newlineInLiteral, "newline in literal") -DIAGNOSTIC(10010, Error, quoteCannotBeDelimiter, "'\"' encountered before '(' in raw string literal. '\"' cannot be a part of a delimiter.") +DIAGNOSTIC( + 10010, + Error, + quoteCannotBeDelimiter, + "'\"' encountered before '(' in raw string literal. '\"' cannot be a part of a delimiter.") DIAGNOSTIC(10011, Error, unexpectedEndOfInput, "unexpected end of input") diff --git a/source/compiler-core/slang-lexer.cpp b/source/compiler-core/slang-lexer.cpp index 366af9114..df95f5f1e 100644 --- a/source/compiler-core/slang-lexer.cpp +++ b/source/compiler-core/slang-lexer.cpp @@ -6,196 +6,197 @@ // #include "core/slang-char-encode.h" +#include "slang-core-diagnostics.h" #include "slang-name.h" #include "slang-source-loc.h" -#include "slang-core-diagnostics.h" namespace Slang { - Token TokenReader::getEndOfFileToken() - { - return Token(TokenType::EndOfFile, UnownedStringSlice::fromLiteral(""), SourceLoc()); - } +Token TokenReader::getEndOfFileToken() +{ + return Token(TokenType::EndOfFile, UnownedStringSlice::fromLiteral(""), SourceLoc()); +} - const Token* TokenList::begin() const - { - SLANG_ASSERT(m_tokens.getCount()); - return &m_tokens[0]; - } +const Token* TokenList::begin() const +{ + SLANG_ASSERT(m_tokens.getCount()); + return &m_tokens[0]; +} - const Token* TokenList::end() const - { - SLANG_ASSERT(m_tokens.getCount()); - SLANG_ASSERT(m_tokens[m_tokens.getCount() - 1].type == TokenType::EndOfFile); - return &m_tokens[m_tokens.getCount() - 1]; - } +const Token* TokenList::end() const +{ + SLANG_ASSERT(m_tokens.getCount()); + SLANG_ASSERT(m_tokens[m_tokens.getCount() - 1].type == TokenType::EndOfFile); + return &m_tokens[m_tokens.getCount() - 1]; +} - TokenSpan::TokenSpan() - : m_begin(nullptr) - , m_end (nullptr) - {} +TokenSpan::TokenSpan() + : m_begin(nullptr), m_end(nullptr) +{ +} - TokenReader::TokenReader() - : m_cursor(nullptr) - , m_end (nullptr) - { - _updateLookaheadToken(); - } +TokenReader::TokenReader() + : m_cursor(nullptr), m_end(nullptr) +{ + _updateLookaheadToken(); +} - Token& TokenReader::peekToken() - { - return m_nextToken; - } +Token& TokenReader::peekToken() +{ + return m_nextToken; +} - TokenType TokenReader::peekTokenType() const - { - return m_nextToken.type; - } +TokenType TokenReader::peekTokenType() const +{ + return m_nextToken.type; +} - SourceLoc TokenReader::peekLoc() const - { - return m_nextToken.loc; - } +SourceLoc TokenReader::peekLoc() const +{ + return m_nextToken.loc; +} - Token TokenReader::advanceToken() - { - Token result = m_nextToken; - if (m_cursor != m_end) - m_cursor++; - _updateLookaheadToken(); - return result; - } +Token TokenReader::advanceToken() +{ + Token result = m_nextToken; + if (m_cursor != m_end) + m_cursor++; + _updateLookaheadToken(); + return result; +} - void TokenReader::_updateLookaheadToken() - { - // We assume here that we can read a token from a non-null `m_cursor` - // *even* in the case where `m_cursor == m_end`, because the invariant - // for lists of tokens is that they should be terminated with and - // end-of-file token, so that there is always a token "one past the end." - // - m_nextToken = m_cursor ? *m_cursor : getEndOfFileToken(); +void TokenReader::_updateLookaheadToken() +{ + // We assume here that we can read a token from a non-null `m_cursor` + // *even* in the case where `m_cursor == m_end`, because the invariant + // for lists of tokens is that they should be terminated with and + // end-of-file token, so that there is always a token "one past the end." + // + m_nextToken = m_cursor ? *m_cursor : getEndOfFileToken(); - // If the token we read came from the end of the sub-sequence we are - // reading, then we will change the token type to an end-of-file token - // so that code that reads from the sequence and expects a terminating - // EOF will find it. - // - // TODO: We might eventually want a way to look at the actual token type - // and not just use EOF in all cases: e.g., when emitting diagnostic - // messages that include the token that is seen. - // - if(m_cursor == m_end) - m_nextToken.type = TokenType::EndOfFile; - } + // If the token we read came from the end of the sub-sequence we are + // reading, then we will change the token type to an end-of-file token + // so that code that reads from the sequence and expects a terminating + // EOF will find it. + // + // TODO: We might eventually want a way to look at the actual token type + // and not just use EOF in all cases: e.g., when emitting diagnostic + // messages that include the token that is seen. + // + if (m_cursor == m_end) + m_nextToken.type = TokenType::EndOfFile; +} - // Lexer +// Lexer - void Lexer::initialize( - SourceView* sourceView, - DiagnosticSink* sink, - NamePool* namePool, - MemoryArena* memoryArena) - { - m_sourceView = sourceView; - m_sink = sink; - m_namePool = namePool; - m_memoryArena = memoryArena; - - auto content = sourceView->getContent(); - - m_begin = content.begin(); - m_cursor = content.begin(); - m_end = content.end(); - - // Set the start location - m_startLoc = sourceView->getRange().begin; - - // The first token read from a translation unit should be considered to be at - // the start of a line, and *also* as coming after whitespace (conceptually - // both the end-of-file and beginning-of-file pseudo-tokens are whitespace). - // - m_tokenFlags = TokenFlag::AtStartOfLine | TokenFlag::AfterWhitespace; - m_lexerFlags = 0; - } +void Lexer::initialize( + SourceView* sourceView, + DiagnosticSink* sink, + NamePool* namePool, + MemoryArena* memoryArena) +{ + m_sourceView = sourceView; + m_sink = sink; + m_namePool = namePool; + m_memoryArena = memoryArena; - Lexer::~Lexer() - { - } + auto content = sourceView->getContent(); - enum { kEOF = -1 }; + m_begin = content.begin(); + m_cursor = content.begin(); + m_end = content.end(); - // Get the next input byte, without any handling of - // escaped newlines, non-ASCII code points, source locations, etc. - static int _peekRaw(Lexer* lexer) - { - // If we are at the end of the input, return a designated end-of-file value - if(lexer->m_cursor == lexer->m_end) - return kEOF; + // Set the start location + m_startLoc = sourceView->getRange().begin; - // Otherwise, just look at the next byte - return *lexer->m_cursor; - } + // The first token read from a translation unit should be considered to be at + // the start of a line, and *also* as coming after whitespace (conceptually + // both the end-of-file and beginning-of-file pseudo-tokens are whitespace). + // + m_tokenFlags = TokenFlag::AtStartOfLine | TokenFlag::AfterWhitespace; + m_lexerFlags = 0; +} - // Read one input byte without any special handling (similar to `peekRaw`) - static int _advanceRaw(Lexer* lexer) - { - // The logic here is basically the same as for `peekRaw()`, - // escape we advance `cursor` if we aren't at the end. +Lexer::~Lexer() {} - if (lexer->m_cursor == lexer->m_end) - return kEOF; +enum +{ + kEOF = -1 +}; - return *lexer->m_cursor++; - } +// Get the next input byte, without any handling of +// escaped newlines, non-ASCII code points, source locations, etc. +static int _peekRaw(Lexer* lexer) +{ + // If we are at the end of the input, return a designated end-of-file value + if (lexer->m_cursor == lexer->m_end) + return kEOF; - // When the cursor is already at the first byte of an end-of-line sequence, - // consume one or two bytes that compose the sequence. - // - // Basically, a newline is one of: - // - // "\n" - // "\r" - // "\r\n" - // "\n\r" - // - // We always look for the longest match possible. - // - static void _handleNewLineInner(Lexer* lexer, int c) - { - SLANG_ASSERT(c == '\n' || c == '\r'); + // Otherwise, just look at the next byte + return *lexer->m_cursor; +} - int d = _peekRaw(lexer); - if( (c ^ d) == ('\n' ^ '\r') ) - { - _advanceRaw(lexer); - } - } +// Read one input byte without any special handling (similar to `peekRaw`) +static int _advanceRaw(Lexer* lexer) +{ + // The logic here is basically the same as for `peekRaw()`, + // escape we advance `cursor` if we aren't at the end. + + if (lexer->m_cursor == lexer->m_end) + return kEOF; + + return *lexer->m_cursor++; +} + +// When the cursor is already at the first byte of an end-of-line sequence, +// consume one or two bytes that compose the sequence. +// +// Basically, a newline is one of: +// +// "\n" +// "\r" +// "\r\n" +// "\n\r" +// +// We always look for the longest match possible. +// +static void _handleNewLineInner(Lexer* lexer, int c) +{ + SLANG_ASSERT(c == '\n' || c == '\r'); - // Look ahead one code point, dealing with complications like - // escaped newlines. - static int _peek(Lexer* lexer, int offset = 0) + int d = _peekRaw(lexer); + if ((c ^ d) == ('\n' ^ '\r')) { - int pos = 0; - int c = kEOF; + _advanceRaw(lexer); + } +} - do - { - if (lexer->m_cursor + pos == lexer->m_end) - return kEOF; +// Look ahead one code point, dealing with complications like +// escaped newlines. +static int _peek(Lexer* lexer, int offset = 0) +{ + int pos = 0; + int c = kEOF; + + do + { + if (lexer->m_cursor + pos == lexer->m_end) + return kEOF; - c = lexer->m_cursor[pos++]; + c = lexer->m_cursor[pos++]; - while (c == '\\') + while (c == '\\') + { + // We might have a backslash-escaped newline. + // Look at the next byte (if any) to see. + // + // Note(tfoley): We are assuming a null-terminated input here, + // so that we can safely look at the next byte without issue. + int d = lexer->m_cursor[pos++]; + switch (d) { - // We might have a backslash-escaped newline. - // Look at the next byte (if any) to see. - // - // Note(tfoley): We are assuming a null-terminated input here, - // so that we can safely look at the next byte without issue. - int d = lexer->m_cursor[pos++]; - switch (d) - { - case '\r': case '\n': + case '\r': + case '\n': { // The newline was escaped, so return the code point after *that* int e = lexer->m_cursor[pos++]; @@ -205,1139 +206,1198 @@ namespace Slang c = e; continue; } - default: - break; - } - - // Only continue this while loop in the case where we consumed - // some newlines - break; - } - if (isUtf8LeadingByte((Byte)c)) - { - // Consume all unicode characters. - pos--; - c = getUnicodePointFromUTF8([&]() {return lexer->m_cursor[pos++]; }); + default: break; } - // Default case is to just hand along the byte we read as an ASCII code point. - } while (offset--); - return c; - } + // Only continue this while loop in the case where we consumed + // some newlines + break; + } + if (isUtf8LeadingByte((Byte)c)) + { + // Consume all unicode characters. + pos--; + c = getUnicodePointFromUTF8([&]() { return lexer->m_cursor[pos++]; }); + } + // Default case is to just hand along the byte we read as an ASCII code point. + } while (offset--); - // Get the next code point from the input, and advance the cursor. - static int _advance(Lexer* lexer) + return c; +} + +// Get the next code point from the input, and advance the cursor. +static int _advance(Lexer* lexer) +{ + // We are going to loop, but only as a way of handling + // escaped line endings. + for (;;) { - // We are going to loop, but only as a way of handling - // escaped line endings. - for (;;) - { - // If we are at the end of the input, then the task is easy. - if (lexer->m_cursor == lexer->m_end) - return kEOF; + // If we are at the end of the input, then the task is easy. + if (lexer->m_cursor == lexer->m_end) + return kEOF; - // Look at the next raw byte, and decide what to do - int c = *lexer->m_cursor++; + // Look at the next raw byte, and decide what to do + int c = *lexer->m_cursor++; - if (c == '\\') + if (c == '\\') + { + // We might have a backslash-escaped newline. + // Look at the next byte (if any) to see. + // + // Note(tfoley): We are assuming a null-terminated input here, + // so that we can safely look at the next byte without issue. + int d = *lexer->m_cursor; + switch (d) { - // We might have a backslash-escaped newline. - // Look at the next byte (if any) to see. - // - // Note(tfoley): We are assuming a null-terminated input here, - // so that we can safely look at the next byte without issue. - int d = *lexer->m_cursor; - switch (d) - { - case '\r': case '\n': - // handle the end-of-line for our source location tracking - lexer->m_cursor++; - _handleNewLineInner(lexer, d); - - lexer->m_tokenFlags |= TokenFlag::ScrubbingNeeded; + case '\r': + case '\n': + // handle the end-of-line for our source location tracking + lexer->m_cursor++; + _handleNewLineInner(lexer, d); - // Now try again, looking at the character after the - // escaped newline. - continue; + lexer->m_tokenFlags |= TokenFlag::ScrubbingNeeded; - default: - break; - } - } + // Now try again, looking at the character after the + // escaped newline. + continue; - // Consume all unicode characters. - if (isUtf8LeadingByte((Byte)c)) - { - lexer->m_cursor--; - c = getUnicodePointFromUTF8([&]() {return *lexer->m_cursor++; }); + default: break; } + } - // Default case is to return the raw byte we saw. - return c; + // Consume all unicode characters. + if (isUtf8LeadingByte((Byte)c)) + { + lexer->m_cursor--; + c = getUnicodePointFromUTF8([&]() { return *lexer->m_cursor++; }); } - } - static void _handleNewLine(Lexer* lexer) - { - int c = _advance(lexer); - _handleNewLineInner(lexer, c); + // Default case is to return the raw byte we saw. + return c; } +} + +static void _handleNewLine(Lexer* lexer) +{ + int c = _advance(lexer); + _handleNewLineInner(lexer, c); +} - static void _lexLineComment(Lexer* lexer) +static void _lexLineComment(Lexer* lexer) +{ + for (;;) { - for(;;) + switch (_peek(lexer)) { - switch(_peek(lexer)) - { - case '\n': case '\r': case kEOF: - return; + case '\n': + case '\r': + case kEOF: return; - default: - _advance(lexer); - continue; - } + default: _advance(lexer); continue; } } +} - static void _lexBlockComment(Lexer* lexer) +static void _lexBlockComment(Lexer* lexer) +{ + for (;;) { - for(;;) + switch (_peek(lexer)) { - switch(_peek(lexer)) - { - case kEOF: - // TODO(tfoley) diagnostic! - return; - - case '\n': case '\r': - _handleNewLine(lexer); - continue; + case kEOF: + // TODO(tfoley) diagnostic! + return; - case '*': - _advance(lexer); - switch( _peek(lexer) ) - { - case '/': - _advance(lexer); - return; + case '\n': + case '\r': _handleNewLine(lexer); continue; - default: - continue; - } + case '*': + _advance(lexer); + switch (_peek(lexer)) + { + case '/': _advance(lexer); return; - default: - _advance(lexer); - continue; + default: continue; } + + default: _advance(lexer); continue; } } +} - static void _lexHorizontalSpace(Lexer* lexer) +static void _lexHorizontalSpace(Lexer* lexer) +{ + for (;;) { - for(;;) + switch (_peek(lexer)) { - switch(_peek(lexer)) - { - case ' ': case '\t': - _advance(lexer); - continue; + case ' ': + case '\t': _advance(lexer); continue; - default: - return; - } + default: return; } } +} - static bool isNonAsciiCodePoint(unsigned int codePoint) - { - return codePoint != 0xFFFFFFFF && codePoint >= 0x80; - } +static bool isNonAsciiCodePoint(unsigned int codePoint) +{ + return codePoint != 0xFFFFFFFF && codePoint >= 0x80; +} - static void _lexIdentifier(Lexer* lexer) +static void _lexIdentifier(Lexer* lexer) +{ + for (;;) { - for(;;) + int c = _peek(lexer); + if (('a' <= c) && (c <= 'z') || ('A' <= c) && (c <= 'Z') || ('0' <= c) && (c <= '9') || + (c == '_') || isNonAsciiCodePoint((unsigned int)c)) { - int c = _peek(lexer); - if(('a' <= c ) && (c <= 'z') - || ('A' <= c) && (c <= 'Z') - || ('0' <= c) && (c <= '9') - || (c == '_') - || isNonAsciiCodePoint((unsigned int)c)) - { - _advance(lexer); - continue; - } - return; + _advance(lexer); + continue; } + return; } +} - static SourceLoc _getSourceLoc(Lexer* lexer) - { - return lexer->m_startLoc + (lexer->m_cursor - lexer->m_begin); - } +static SourceLoc _getSourceLoc(Lexer* lexer) +{ + return lexer->m_startLoc + (lexer->m_cursor - lexer->m_begin); +} - static void _lexDigits(Lexer* lexer, int base) +static void _lexDigits(Lexer* lexer, int base) +{ + for (;;) { - for(;;) - { - int c = _peek(lexer); - - int digitVal = 0; - switch(c) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - digitVal = c - '0'; - break; - - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - if(base <= 10) return; - digitVal = 10 + c - 'a'; - break; + int c = _peek(lexer); - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - if(base <= 10) return; - digitVal = 10 + c - 'A'; - break; - - default: - // Not more digits! + int digitVal = 0; + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': digitVal = c - '0'; break; + + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + if (base <= 10) return; - } + digitVal = 10 + c - 'a'; + break; - if(digitVal >= base) - { - if (auto sink = lexer->getDiagnosticSink()) - { - char buffer[] = { (char) c, 0 }; - sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::invalidDigitForBase, buffer, base); - } - } + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + if (base <= 10) + return; + digitVal = 10 + c - 'A'; + break; - _advance(lexer); + default: + // Not more digits! + return; } - } - static TokenType _maybeLexNumberSuffix(Lexer* lexer, TokenType tokenType) - { - // Be liberal in what we accept here, so that figuring out - // the semantics of a numeric suffix is left up to the parser - // and semantic checking logic. - // - for( ;;) + if (digitVal >= base) { - int c = _peek(lexer); - - // Accept any alphanumeric character, plus underscores. - if(('a' <= c ) && (c <= 'z') - || ('A' <= c) && (c <= 'Z') - || ('0' <= c) && (c <= '9') - || (c == '_')) + if (auto sink = lexer->getDiagnosticSink()) { - _advance(lexer); - continue; + char buffer[] = {(char)c, 0}; + sink->diagnose( + _getSourceLoc(lexer), + LexerDiagnostics::invalidDigitForBase, + buffer, + base); } - - // Stop at the first character that isn't - // alphanumeric. - return tokenType; } + + _advance(lexer); } +} - static bool _isNumberExponent(int c, int base) +static TokenType _maybeLexNumberSuffix(Lexer* lexer, TokenType tokenType) +{ + // Be liberal in what we accept here, so that figuring out + // the semantics of a numeric suffix is left up to the parser + // and semantic checking logic. + // + for (;;) { - switch( c ) - { - default: - return false; + int c = _peek(lexer); - case 'e': case 'E': - if(base != 10) return false; - break; - - case 'p': case 'P': - if(base != 16) return false; - break; + // Accept any alphanumeric character, plus underscores. + if (('a' <= c) && (c <= 'z') || ('A' <= c) && (c <= 'Z') || ('0' <= c) && (c <= '9') || + (c == '_')) + { + _advance(lexer); + continue; } - return true; + // Stop at the first character that isn't + // alphanumeric. + return tokenType; } +} - static bool _maybeLexNumberExponent(Lexer* lexer, int base) +static bool _isNumberExponent(int c, int base) +{ + switch (c) { - if (_peek(lexer) == '#') - { - // Special case #INF - const auto inf = toSlice("#INF"); - for (auto c : inf) - { - if (_peek(lexer) != c) - { - return false; - } - _advance(lexer); - } + default: return false; - return true; - } + case 'e': + case 'E': + if (base != 10) + return false; + break; - if(!_isNumberExponent(_peek(lexer), base)) + case 'p': + case 'P': + if (base != 16) return false; + break; + } - // we saw an exponent marker - _advance(lexer); + return true; +} - // Now start to read the exponent - switch( _peek(lexer) ) +static bool _maybeLexNumberExponent(Lexer* lexer, int base) +{ + if (_peek(lexer) == '#') + { + // Special case #INF + const auto inf = toSlice("#INF"); + for (auto c : inf) { - case '+': case '-': + if (_peek(lexer) != c) + { + return false; + } _advance(lexer); - break; } - // TODO(tfoley): it would be an error to not see digits here... - - _lexDigits(lexer, 10); - return true; } - static TokenType _lexNumberAfterDecimalPoint(Lexer* lexer, int base) - { - _lexDigits(lexer, base); - _maybeLexNumberExponent(lexer, base); + if (!_isNumberExponent(_peek(lexer), base)) + return false; - return _maybeLexNumberSuffix(lexer, TokenType::FloatingPointLiteral); - } + // we saw an exponent marker + _advance(lexer); - static TokenType _lexNumber(Lexer* lexer, int base) + // Now start to read the exponent + switch (_peek(lexer)) { - // TODO(tfoley): Need to consider whether to allow any kind of digit separator character. + case '+': + case '-': _advance(lexer); break; + } - TokenType tokenType = TokenType::IntegerLiteral; + // TODO(tfoley): it would be an error to not see digits here... - // At the start of things, we just concern ourselves with digits - _lexDigits(lexer, base); + _lexDigits(lexer, 10); - if( _peek(lexer) == '.' ) - { - switch (_peek(lexer, 1)) - { - // 123.xxxx or 123.rrrr - case 'x': - case 'r': - break; + return true; +} - default: - tokenType = TokenType::FloatingPointLiteral; +static TokenType _lexNumberAfterDecimalPoint(Lexer* lexer, int base) +{ + _lexDigits(lexer, base); + _maybeLexNumberExponent(lexer, base); - _advance(lexer); - _lexDigits(lexer, base); - } - } + return _maybeLexNumberSuffix(lexer, TokenType::FloatingPointLiteral); +} + +static TokenType _lexNumber(Lexer* lexer, int base) +{ + // TODO(tfoley): Need to consider whether to allow any kind of digit separator character. + + TokenType tokenType = TokenType::IntegerLiteral; - if( _maybeLexNumberExponent(lexer, base)) + // At the start of things, we just concern ourselves with digits + _lexDigits(lexer, base); + + if (_peek(lexer) == '.') + { + switch (_peek(lexer, 1)) { + // 123.xxxx or 123.rrrr + case 'x': + case 'r': break; + + default: tokenType = TokenType::FloatingPointLiteral; - } - _maybeLexNumberSuffix(lexer, tokenType); - return tokenType; + _advance(lexer); + _lexDigits(lexer, base); + } } - static int _maybeReadDigit(char const** ioCursor, int base) + if (_maybeLexNumberExponent(lexer, base)) { - auto& cursor = *ioCursor; + tokenType = TokenType::FloatingPointLiteral; + } - for(;;) - { - int c = *cursor; - switch(c) - { - default: - return -1; + _maybeLexNumberSuffix(lexer, tokenType); + return tokenType; +} - // TODO: need to decide on digit separator characters - case '_': - cursor++; - continue; +static int _maybeReadDigit(char const** ioCursor, int base) +{ + auto& cursor = *ioCursor; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - cursor++; - return c - '0'; + for (;;) + { + int c = *cursor; + switch (c) + { + default: return -1; - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - if(base > 10) - { - cursor++; - return 10 + c - 'a'; - } - return -1; + // TODO: need to decide on digit separator characters + case '_': cursor++; continue; - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - if(base > 10) - { - cursor++; - return 10 + c - 'A'; - } - return -1; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': cursor++; return c - '0'; + + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + if (base > 10) + { + cursor++; + return 10 + c - 'a'; + } + return -1; + + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + if (base > 10) + { + cursor++; + return 10 + c - 'A'; } + return -1; } } +} - static int _readOptionalBase(char const** ioCursor) +static int _readOptionalBase(char const** ioCursor) +{ + auto& cursor = *ioCursor; + if (*cursor == '0') { - auto& cursor = *ioCursor; - if( *cursor == '0' ) + cursor++; + switch (*cursor) { - cursor++; - switch(*cursor) - { - case 'x': case 'X': - cursor++; - return 16; - - case 'b': case 'B': - cursor++; - return 2; + case 'x': + case 'X': cursor++; return 16; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - return 8; + case 'b': + case 'B': cursor++; return 2; - default: - return 10; - } + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': return 8; + + default: return 10; } - - return 10; } + return 10; +} - IntegerLiteralValue getIntegerLiteralValue(Token const& token, UnownedStringSlice* outSuffix) - { - IntegerLiteralValue value = 0; - - const UnownedStringSlice content = token.getContent(); - - char const* cursor = content.begin(); - char const* end = content.end(); +IntegerLiteralValue getIntegerLiteralValue(Token const& token, UnownedStringSlice* outSuffix) +{ + IntegerLiteralValue value = 0; - int base = _readOptionalBase(&cursor); + const UnownedStringSlice content = token.getContent(); - for( ;;) - { - int digit = _maybeReadDigit(&cursor, base); - if(digit < 0) - break; + char const* cursor = content.begin(); + char const* end = content.end(); - value = value*base + digit; - } + int base = _readOptionalBase(&cursor); - if(outSuffix) - { - *outSuffix = UnownedStringSlice(cursor, end); - } + for (;;) + { + int digit = _maybeReadDigit(&cursor, base); + if (digit < 0) + break; - return value; + value = value * base + digit; } - FloatingPointLiteralValue getFloatingPointLiteralValue(Token const& token, UnownedStringSlice* outSuffix) + if (outSuffix) { - FloatingPointLiteralValue value = 0; + *outSuffix = UnownedStringSlice(cursor, end); + } + + return value; +} + +FloatingPointLiteralValue getFloatingPointLiteralValue( + Token const& token, + UnownedStringSlice* outSuffix) +{ + FloatingPointLiteralValue value = 0; - const UnownedStringSlice content = token.getContent(); + const UnownedStringSlice content = token.getContent(); - char const* cursor = content.begin(); - char const* end = content.end(); + char const* cursor = content.begin(); + char const* end = content.end(); - int radix = _readOptionalBase(&cursor); + int radix = _readOptionalBase(&cursor); - bool seenDot = false; - FloatingPointLiteralValue divisor = 1; - for( ;;) + bool seenDot = false; + FloatingPointLiteralValue divisor = 1; + for (;;) + { + if (*cursor == '.') { - if(*cursor == '.') - { - cursor++; - seenDot = true; - continue; - } + cursor++; + seenDot = true; + continue; + } - int digit = _maybeReadDigit(&cursor, radix); - if(digit < 0) - break; + int digit = _maybeReadDigit(&cursor, radix); + if (digit < 0) + break; - value = value*radix + digit; + value = value * radix + digit; - if(seenDot) - { - divisor *= radix; - } + if (seenDot) + { + divisor *= radix; } + } - if (*cursor == '#') - { - // It must be INF - const auto inf = toSlice("#INF"); + if (*cursor == '#') + { + // It must be INF + const auto inf = toSlice("#INF"); - if (UnownedStringSlice(cursor, end).startsWith(inf)) + if (UnownedStringSlice(cursor, end).startsWith(inf)) + { + if (outSuffix) { - if(outSuffix) - { - *outSuffix = UnownedStringSlice(cursor + inf.getLength(), end); - } + *outSuffix = UnownedStringSlice(cursor + inf.getLength(), end); + } - value = INFINITY; + value = INFINITY; - return value; - } + return value; } + } - // Now read optional exponent - if(_isNumberExponent(*cursor, radix)) + // Now read optional exponent + if (_isNumberExponent(*cursor, radix)) + { + cursor++; + + bool exponentIsNegative = false; + switch (*cursor) { + default: break; + + case '-': + exponentIsNegative = true; cursor++; + break; - bool exponentIsNegative = false; - switch(*cursor) - { - default: - break; + case '+': cursor++; break; + } - case '-': - exponentIsNegative = true; - cursor++; - break; + int exponentRadix = 10; + int exponent = 0; - case '+': - cursor++; + for (;;) + { + int digit = _maybeReadDigit(&cursor, exponentRadix); + if (digit < 0) break; - } - - int exponentRadix = 10; - int exponent = 0; - - for(;;) - { - int digit = _maybeReadDigit(&cursor, exponentRadix); - if(digit < 0) - break; - - exponent = exponent*exponentRadix + digit; - } - - FloatingPointLiteralValue exponentBase = 10; - if(radix == 16) - { - exponentBase = 2; - } - FloatingPointLiteralValue exponentValue = pow(exponentBase, exponent); + exponent = exponent * exponentRadix + digit; + } - if( exponentIsNegative ) - { - divisor *= exponentValue; - } - else - { - value *= exponentValue; - } + FloatingPointLiteralValue exponentBase = 10; + if (radix == 16) + { + exponentBase = 2; } - value /= divisor; + FloatingPointLiteralValue exponentValue = pow(exponentBase, exponent); - if(outSuffix) + if (exponentIsNegative) + { + divisor *= exponentValue; + } + else { - *outSuffix = UnownedStringSlice(cursor, end); + value *= exponentValue; } + } - return value; + value /= divisor; + + if (outSuffix) + { + *outSuffix = UnownedStringSlice(cursor, end); } - static void _lexStringLiteralBody(Lexer* lexer, char quote) + return value; +} + +static void _lexStringLiteralBody(Lexer* lexer, char quote) +{ + for (;;) { - for(;;) + int c = _peek(lexer); + if (c == quote) + { + _advance(lexer); + return; + } + + switch (c) { - int c = _peek(lexer); - if(c == quote) + case kEOF: + if (auto sink = lexer->getDiagnosticSink()) { - _advance(lexer); - return; + sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::endOfFileInLiteral); } + return; - switch(c) + case '\n': + case '\r': + if (auto sink = lexer->getDiagnosticSink()) { - case kEOF: - if (auto sink = lexer->getDiagnosticSink()) - { - sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::endOfFileInLiteral); - } - return; + sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::newlineInLiteral); + } + return; - case '\n': case '\r': - if (auto sink = lexer->getDiagnosticSink()) + case '\\': + // Need to handle various escape sequence cases + _advance(lexer); + switch (_peek(lexer)) + { + case '\'': + case '\"': + case '\\': + case '?': + case 'a': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + case 'v': _advance(lexer); break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + // octal escape: up to 3 characters + _advance(lexer); + for (int ii = 0; ii < 3; ++ii) { - sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::newlineInLiteral); + int d = _peek(lexer); + if (('0' <= d) && (d <= '7')) + { + _advance(lexer); + continue; + } + else + { + break; + } } - return; + break; - case '\\': - // Need to handle various escape sequence cases + case 'x': + // hexadecimal escape: any number of characters _advance(lexer); - switch(_peek(lexer)) + for (;;) { - case '\'': - case '\"': - case '\\': - case '?': - case 'a': - case 'b': - case 'f': - case 'n': - case 'r': - case 't': - case 'v': - _advance(lexer); - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': - // octal escape: up to 3 characters - _advance(lexer); - for(int ii = 0; ii < 3; ++ii) + int d = _peek(lexer); + if (('0' <= d) && (d <= '9') || ('a' <= d) && (d <= 'f') || + ('A' <= d) && (d <= 'F')) { - int d = _peek(lexer); - if(('0' <= d) && (d <= '7')) - { - _advance(lexer); - continue; - } - else - { - break; - } + _advance(lexer); + continue; } - break; - - case 'x': - // hexadecimal escape: any number of characters - _advance(lexer); - for(;;) + else { - int d = _peek(lexer); - if(('0' <= d) && (d <= '9') - || ('a' <= d) && (d <= 'f') - || ('A' <= d) && (d <= 'F')) - { - _advance(lexer); - continue; - } - else - { - break; - } + break; } - break; - - // TODO: Unicode escape sequences - } break; - default: - _advance(lexer); - continue; + // TODO: Unicode escape sequences } + break; + + default: _advance(lexer); continue; } } +} - static void _lexRawStringLiteralBody(Lexer* lexer) +static void _lexRawStringLiteralBody(Lexer* lexer) +{ + const char* start = lexer->m_cursor; + const char* endOfDelimiter = nullptr; + for (;;) { - const char* start = lexer->m_cursor; - const char* endOfDelimiter = nullptr; - for (;;) + int c = _peek(lexer); + if (c == '(' && endOfDelimiter == nullptr) + endOfDelimiter = lexer->m_cursor; + if (c == '\"') { - int c = _peek(lexer); - if (c == '(' && endOfDelimiter == nullptr) - endOfDelimiter = lexer->m_cursor; - if (c == '\"') + if (!endOfDelimiter) { - if (!endOfDelimiter) + if (auto sink = lexer->getDiagnosticSink()) { - if (auto sink = lexer->getDiagnosticSink()) - { - sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::quoteCannotBeDelimiter); - } + sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::quoteCannotBeDelimiter); } - else + } + else + { + auto testStart = lexer->m_cursor - (endOfDelimiter - start); + if (testStart > endOfDelimiter) { - auto testStart = lexer->m_cursor - (endOfDelimiter - start); - if (testStart > endOfDelimiter) + auto testDelimiter = UnownedStringSlice(testStart, lexer->m_cursor); + auto delimiter = UnownedStringSlice(start, endOfDelimiter); + if (*(testStart - 1) == ')' && testDelimiter == delimiter) { - auto testDelimiter = UnownedStringSlice(testStart, lexer->m_cursor); - auto delimiter = UnownedStringSlice(start, endOfDelimiter); - if (*(testStart - 1) == ')' && testDelimiter == delimiter) - { - _advance(lexer); - return; - } + _advance(lexer); + return; } } } + } - switch (c) + switch (c) + { + case kEOF: + if (auto sink = lexer->getDiagnosticSink()) { - case kEOF: - if (auto sink = lexer->getDiagnosticSink()) - { - sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::endOfFileInLiteral); - } - return; - default: - _advance(lexer); - continue; + sink->diagnose(_getSourceLoc(lexer), LexerDiagnostics::endOfFileInLiteral); } + return; + default: _advance(lexer); continue; } } +} - UnownedStringSlice getRawStringLiteralTokenValue(Token const& token) - { - auto content = token.getContent(); - if (content.getLength() <= 5) - return UnownedStringSlice(); - auto start = content.begin() + 2; - auto delimEnd = start; - while (delimEnd < content.end() && *delimEnd != '(') - delimEnd++; - auto delimLength = delimEnd - start; - auto contentEnd = content.end() - delimLength - 2; - auto contentBegin = start + delimLength + 1; - if (contentEnd <= contentBegin) - return UnownedStringSlice(); - return UnownedStringSlice(contentBegin, contentEnd); - } +UnownedStringSlice getRawStringLiteralTokenValue(Token const& token) +{ + auto content = token.getContent(); + if (content.getLength() <= 5) + return UnownedStringSlice(); + auto start = content.begin() + 2; + auto delimEnd = start; + while (delimEnd < content.end() && *delimEnd != '(') + delimEnd++; + auto delimLength = delimEnd - start; + auto contentEnd = content.end() - delimLength - 2; + auto contentBegin = start + delimLength + 1; + if (contentEnd <= contentBegin) + return UnownedStringSlice(); + return UnownedStringSlice(contentBegin, contentEnd); +} - String getStringLiteralTokenValue(Token const& token) - { - SLANG_ASSERT(token.type == TokenType::StringLiteral - || token.type == TokenType::CharLiteral); +String getStringLiteralTokenValue(Token const& token) +{ + SLANG_ASSERT(token.type == TokenType::StringLiteral || token.type == TokenType::CharLiteral); - if (token.getContent().startsWith("R")) - return getRawStringLiteralTokenValue(token); + if (token.getContent().startsWith("R")) + return getRawStringLiteralTokenValue(token); - const UnownedStringSlice content = token.getContent(); + const UnownedStringSlice content = token.getContent(); - char const* cursor = content.begin(); - char const* end = content.end(); - SLANG_UNREFERENCED_VARIABLE(end); + char const* cursor = content.begin(); + char const* end = content.end(); + SLANG_UNREFERENCED_VARIABLE(end); - auto quote = *cursor++; - SLANG_ASSERT(quote == '\'' || quote == '"'); + auto quote = *cursor++; + SLANG_ASSERT(quote == '\'' || quote == '"'); - StringBuilder valueBuilder; - for(;;) - { - SLANG_ASSERT(cursor != end); + StringBuilder valueBuilder; + for (;;) + { + SLANG_ASSERT(cursor != end); - auto c = *cursor++; + auto c = *cursor++; - // If we see a closing quote, then we are at the end of the string literal - if(c == quote) - { - SLANG_ASSERT(cursor == end); - return valueBuilder.produceString(); - } + // If we see a closing quote, then we are at the end of the string literal + if (c == quote) + { + SLANG_ASSERT(cursor == end); + return valueBuilder.produceString(); + } - // Characters that don't being escape sequences are easy; - // just append them to the buffer and move on. - if(c != '\\') - { - valueBuilder.append(c); - continue; - } + // Characters that don't being escape sequences are easy; + // just append them to the buffer and move on. + if (c != '\\') + { + valueBuilder.append(c); + continue; + } - // Now we look at another character to figure out the kind of - // escape sequence we are dealing with: + // Now we look at another character to figure out the kind of + // escape sequence we are dealing with: - char d = *cursor++; + char d = *cursor++; - switch(d) + switch (d) + { + // Simple characters that just needed to be escaped + case '\'': + case '\"': + case '\\': + case '?': valueBuilder.append(d); continue; + + // Traditional escape sequences for special characters + case 'a': valueBuilder.append('\a'); continue; + case 'b': valueBuilder.append('\b'); continue; + case 'f': valueBuilder.append('\f'); continue; + case 'n': valueBuilder.append('\n'); continue; + case 'r': valueBuilder.append('\r'); continue; + case 't': valueBuilder.append('\t'); continue; + case 'v': valueBuilder.append('\v'); continue; + + // Octal escape: up to 3 characters + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': { - // Simple characters that just needed to be escaped - case '\'': - case '\"': - case '\\': - case '?': - valueBuilder.append(d); - continue; - - // Traditional escape sequences for special characters - case 'a': valueBuilder.append('\a'); continue; - case 'b': valueBuilder.append('\b'); continue; - case 'f': valueBuilder.append('\f'); continue; - case 'n': valueBuilder.append('\n'); continue; - case 'r': valueBuilder.append('\r'); continue; - case 't': valueBuilder.append('\t'); continue; - case 'v': valueBuilder.append('\v'); continue; - - // Octal escape: up to 3 characters - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': + cursor--; + int value = 0; + for (int ii = 0; ii < 3; ++ii) { - cursor--; - int value = 0; - for(int ii = 0; ii < 3; ++ii) + d = *cursor; + if (('0' <= d) && (d <= '7')) { - d = *cursor; - if(('0' <= d) && (d <= '7')) - { - value = value*8 + (d - '0'); + value = value * 8 + (d - '0'); - cursor++; - continue; - } - else - { - break; - } + cursor++; + continue; + } + else + { + break; } - - // TODO: add support for appending an arbitrary code point? - valueBuilder.append((char) value); } - continue; - // Hexadecimal escape: any number of characters - case 'x': + // TODO: add support for appending an arbitrary code point? + valueBuilder.append((char)value); + } + continue; + + // Hexadecimal escape: any number of characters + case 'x': + { + int value = 0; + for (;;) { - int value = 0; - for(;;) + d = *cursor++; + int digitValue = 0; + if (('0' <= d) && (d <= '9')) { - d = *cursor++; - int digitValue = 0; - if(('0' <= d) && (d <= '9')) - { - digitValue = d - '0'; - } - else if( ('a' <= d) && (d <= 'f') ) - { - digitValue = d - 'a'; - } - else if( ('A' <= d) && (d <= 'F') ) - { - digitValue = d - 'A'; - } - else - { - cursor--; - break; - } - - value = value*16 + digitValue; + digitValue = d - '0'; + } + else if (('a' <= d) && (d <= 'f')) + { + digitValue = d - 'a'; + } + else if (('A' <= d) && (d <= 'F')) + { + digitValue = d - 'A'; + } + else + { + cursor--; + break; } - // TODO: add support for appending an arbitrary code point? - valueBuilder.append((char) value); + value = value * 16 + digitValue; } - continue; - - // TODO: Unicode escape sequences + // TODO: add support for appending an arbitrary code point? + valueBuilder.append((char)value); } + continue; + + // TODO: Unicode escape sequences } } +} - String getFileNameTokenValue(Token const& token) - { - const UnownedStringSlice content = token.getContent(); +String getFileNameTokenValue(Token const& token) +{ + const UnownedStringSlice content = token.getContent(); - // A file name usually doesn't process escape sequences - // (this is import on Windows, where `\\` is a valid - // path separator character). + // A file name usually doesn't process escape sequences + // (this is import on Windows, where `\\` is a valid + // path separator character). - // Just trim off the first and last characters to remove the quotes - // (whether they were `""` or `<>`. - return String(content.begin() + 1, content.end() - 1); - } + // Just trim off the first and last characters to remove the quotes + // (whether they were `""` or `<>`. + return String(content.begin() + 1, content.end() - 1); +} - static TokenType _lexTokenImpl(Lexer* lexer) +static TokenType _lexTokenImpl(Lexer* lexer) +{ + int nextCodePoint = _peek(lexer); + switch (nextCodePoint) { - int nextCodePoint = _peek(lexer); - switch(nextCodePoint) - { - default: - break; + default: break; - case kEOF: - return TokenType::EndOfFile; + case kEOF: return TokenType::EndOfFile; - case '\r': case '\n': - _handleNewLine(lexer); - return TokenType::NewLine; + case '\r': + case '\n': _handleNewLine(lexer); return TokenType::NewLine; - case ' ': case '\t': - _lexHorizontalSpace(lexer); - return TokenType::WhiteSpace; + case ' ': + case '\t': _lexHorizontalSpace(lexer); return TokenType::WhiteSpace; + + case '.': + _advance(lexer); + switch (_peek(lexer)) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': return _lexNumberAfterDecimalPoint(lexer, 10); case '.': + // Note: consuming the second `.` here means that + // we cannot back up and return a `.` token by itself + // any more. We thus end up having distinct tokens for + // `.`, `..`, and `...` even though the `..` case is + // not part of HLSL. + // _advance(lexer); - switch(_peek(lexer)) + switch (_peek(lexer)) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - return _lexNumberAfterDecimalPoint(lexer, 10); - - case '.': - // Note: consuming the second `.` here means that - // we cannot back up and return a `.` token by itself - // any more. We thus end up having distinct tokens for - // `.`, `..`, and `...` even though the `..` case is - // not part of HLSL. - // - _advance(lexer); - switch(_peek(lexer)) - { - case '.': - _advance(lexer); - return TokenType::Ellipsis; - - default: - return TokenType::DotDot; - } + case '.': _advance(lexer); return TokenType::Ellipsis; - default: - return TokenType::Dot; + default: return TokenType::DotDot; } - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - return _lexNumber(lexer, 10); + default: return TokenType::Dot; + } - case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': return _lexNumber(lexer, 10); + + case '0': + { + auto loc = _getSourceLoc(lexer); + _advance(lexer); + switch (_peek(lexer)) { - auto loc = _getSourceLoc(lexer); - _advance(lexer); - switch(_peek(lexer)) - { - default: - return _maybeLexNumberSuffix(lexer, TokenType::IntegerLiteral); - - case '.': - switch (_peek(lexer, 1)) - { - // 0.xxxx or 0.rrrr - case 'x': - case 'r': - return _maybeLexNumberSuffix(lexer, TokenType::IntegerLiteral); - default: - _advance(lexer); - return _lexNumberAfterDecimalPoint(lexer, 10); - } - - case 'x': case 'X': - _advance(lexer); - return _lexNumber(lexer, 16); + default: return _maybeLexNumberSuffix(lexer, TokenType::IntegerLiteral); - case 'b': case 'B': - _advance(lexer); - return _lexNumber(lexer, 2); - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if (auto sink = lexer->getDiagnosticSink()) - { - sink->diagnose(loc, LexerDiagnostics::octalLiteral); - } - return _lexNumber(lexer, 8); + case '.': + switch (_peek(lexer, 1)) + { + // 0.xxxx or 0.rrrr + case 'x': + case 'r': return _maybeLexNumberSuffix(lexer, TokenType::IntegerLiteral); + default: _advance(lexer); return _lexNumberAfterDecimalPoint(lexer, 10); } - } - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': case 'g': case 'h': case 'i': case 'j': - case 'k': case 'l': case 'm': case 'n': case 'o': - case 'p': case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'x': case 'y': - case 'z': - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': case 'G': case 'H': case 'I': case 'J': - case 'K': case 'L': case 'M': case 'N': case 'O': - case 'P': case 'Q': case 'S': case 'T': - case 'U': case 'V': case 'W': case 'X': case 'Y': - case 'Z': - case '_': - _lexIdentifier(lexer); - return TokenType::Identifier; - case 'R': - _advance(lexer); - switch (_peek(lexer)) - { - default: - _lexIdentifier(lexer); - return TokenType::Identifier; - case '\"': - _advance(lexer); - _lexRawStringLiteralBody(lexer); - return TokenType::StringLiteral; + case 'x': + case 'X': _advance(lexer); return _lexNumber(lexer, 16); + + case 'b': + case 'B': _advance(lexer); return _lexNumber(lexer, 2); + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (auto sink = lexer->getDiagnosticSink()) + { + sink->diagnose(loc, LexerDiagnostics::octalLiteral); + } + return _lexNumber(lexer, 8); } + } + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '_': _lexIdentifier(lexer); return TokenType::Identifier; + case 'R': + _advance(lexer); + switch (_peek(lexer)) + { + default: _lexIdentifier(lexer); return TokenType::Identifier; case '\"': _advance(lexer); - _lexStringLiteralBody(lexer, '\"'); + _lexRawStringLiteralBody(lexer); return TokenType::StringLiteral; + } - case '\'': - _advance(lexer); - _lexStringLiteralBody(lexer, '\''); - return TokenType::CharLiteral; + case '\"': + _advance(lexer); + _lexStringLiteralBody(lexer, '\"'); + return TokenType::StringLiteral; + case '\'': + _advance(lexer); + _lexStringLiteralBody(lexer, '\''); + return TokenType::CharLiteral; - case '+': - _advance(lexer); - switch(_peek(lexer)) - { - case '+': _advance(lexer); return TokenType::OpInc; - case '=': _advance(lexer); return TokenType::OpAddAssign; - default: - return TokenType::OpAdd; - } - case '-': - _advance(lexer); - switch(_peek(lexer)) - { - case '-': _advance(lexer); return TokenType::OpDec; - case '=': _advance(lexer); return TokenType::OpSubAssign; - case '>': _advance(lexer); return TokenType::RightArrow; - default: - return TokenType::OpSub; - } + case '+': + _advance(lexer); + switch (_peek(lexer)) + { + case '+': _advance(lexer); return TokenType::OpInc; + case '=': _advance(lexer); return TokenType::OpAddAssign; + default: return TokenType::OpAdd; + } - case '*': - _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpMulAssign; - default: - return TokenType::OpMul; - } + case '-': + _advance(lexer); + switch (_peek(lexer)) + { + case '-': _advance(lexer); return TokenType::OpDec; + case '=': _advance(lexer); return TokenType::OpSubAssign; + case '>': _advance(lexer); return TokenType::RightArrow; + default: return TokenType::OpSub; + } + + case '*': + _advance(lexer); + switch (_peek(lexer)) + { + case '=': _advance(lexer); return TokenType::OpMulAssign; + default: return TokenType::OpMul; + } + case '/': + _advance(lexer); + switch (_peek(lexer)) + { + case '=': _advance(lexer); return TokenType::OpDivAssign; case '/': _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpDivAssign; - case '/': _advance(lexer); _lexLineComment(lexer); return TokenType::LineComment; - case '*': _advance(lexer); _lexBlockComment(lexer); return TokenType::BlockComment; - default: - return TokenType::OpDiv; - } - - case '%': + _lexLineComment(lexer); + return TokenType::LineComment; + case '*': _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpModAssign; - default: - return TokenType::OpMod; - } + _lexBlockComment(lexer); + return TokenType::BlockComment; + default: return TokenType::OpDiv; + } - case '|': - _advance(lexer); - switch(_peek(lexer)) - { - case '|': _advance(lexer); return TokenType::OpOr; - case '=': _advance(lexer); return TokenType::OpOrAssign; - default: - return TokenType::OpBitOr; - } + case '%': + _advance(lexer); + switch (_peek(lexer)) + { + case '=': _advance(lexer); return TokenType::OpModAssign; + default: return TokenType::OpMod; + } - case '&': - _advance(lexer); - switch(_peek(lexer)) - { - case '&': _advance(lexer); return TokenType::OpAnd; - case '=': _advance(lexer); return TokenType::OpAndAssign; - default: - return TokenType::OpBitAnd; - } + case '|': + _advance(lexer); + switch (_peek(lexer)) + { + case '|': _advance(lexer); return TokenType::OpOr; + case '=': _advance(lexer); return TokenType::OpOrAssign; + default: return TokenType::OpBitOr; + } - case '^': - _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpXorAssign; - default: - return TokenType::OpBitXor; - } + case '&': + _advance(lexer); + switch (_peek(lexer)) + { + case '&': _advance(lexer); return TokenType::OpAnd; + case '=': _advance(lexer); return TokenType::OpAndAssign; + default: return TokenType::OpBitAnd; + } + + case '^': + _advance(lexer); + switch (_peek(lexer)) + { + case '=': _advance(lexer); return TokenType::OpXorAssign; + default: return TokenType::OpBitXor; + } + case '>': + _advance(lexer); + switch (_peek(lexer)) + { case '>': _advance(lexer); - switch(_peek(lexer)) + switch (_peek(lexer)) { - case '>': - _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpShrAssign; - default: return TokenType::OpRsh; - } - case '=': _advance(lexer); return TokenType::OpGeq; - default: - return TokenType::OpGreater; + case '=': _advance(lexer); return TokenType::OpShrAssign; + default: return TokenType::OpRsh; } + case '=': _advance(lexer); return TokenType::OpGeq; + default: return TokenType::OpGreater; + } + case '<': + _advance(lexer); + switch (_peek(lexer)) + { case '<': _advance(lexer); - switch(_peek(lexer)) + switch (_peek(lexer)) { - case '<': - _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpShlAssign; - default: return TokenType::OpLsh; - } - case '=': _advance(lexer); return TokenType::OpLeq; - default: - return TokenType::OpLess; + case '=': _advance(lexer); return TokenType::OpShlAssign; + default: return TokenType::OpLsh; } + case '=': _advance(lexer); return TokenType::OpLeq; + default: return TokenType::OpLess; + } - case '=': - _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpEql; - default: - return TokenType::OpAssign; - } + case '=': + _advance(lexer); + switch (_peek(lexer)) + { + case '=': _advance(lexer); return TokenType::OpEql; + default: return TokenType::OpAssign; + } - case '!': - _advance(lexer); - switch(_peek(lexer)) - { - case '=': _advance(lexer); return TokenType::OpNeq; - default: - return TokenType::OpNot; - } + case '!': + _advance(lexer); + switch (_peek(lexer)) + { + case '=': _advance(lexer); return TokenType::OpNeq; + default: return TokenType::OpNot; + } - case '#': - _advance(lexer); - switch(_peek(lexer)) - { - case '#': _advance(lexer); return TokenType::PoundPound; + case '#': + _advance(lexer); + switch (_peek(lexer)) + { + case '#': _advance(lexer); return TokenType::PoundPound; - case '?': _advance(lexer); return TokenType::CompletionRequest; + case '?': _advance(lexer); return TokenType::CompletionRequest; - default: - return TokenType::Pound; - } + default: return TokenType::Pound; + } - case '~': _advance(lexer); return TokenType::OpBitNot; + case '~': _advance(lexer); return TokenType::OpBitNot; - case ':': + case ':': { _advance(lexer); if (_peek(lexer) == ':') @@ -1347,151 +1407,154 @@ namespace Slang } return TokenType::Colon; } - case ';': _advance(lexer); return TokenType::Semicolon; - case ',': _advance(lexer); return TokenType::Comma; - - case '{': _advance(lexer); return TokenType::LBrace; - case '}': _advance(lexer); return TokenType::RBrace; - case '[': _advance(lexer); return TokenType::LBracket; - case ']': _advance(lexer); return TokenType::RBracket; - case '(': _advance(lexer); return TokenType::LParent; - case ')': _advance(lexer); return TokenType::RParent; - - case '?': _advance(lexer); return TokenType::QuestionMark; - case '@': _advance(lexer); return TokenType::At; - case '$': + case ';': _advance(lexer); return TokenType::Semicolon; + case ',': _advance(lexer); return TokenType::Comma; + + case '{': _advance(lexer); return TokenType::LBrace; + case '}': _advance(lexer); return TokenType::RBrace; + case '[': _advance(lexer); return TokenType::LBracket; + case ']': _advance(lexer); return TokenType::RBracket; + case '(': _advance(lexer); return TokenType::LParent; + case ')': _advance(lexer); return TokenType::RParent; + + case '?': _advance(lexer); return TokenType::QuestionMark; + case '@': _advance(lexer); return TokenType::At; + case '$': { _advance(lexer); - if(_peek(lexer) == '$') + if (_peek(lexer) == '$') { _advance(lexer); return TokenType::DollarDollar; } return TokenType::Dollar; } + } - } - - // We treat all unicode characters as a part of an identifier. - if (isNonAsciiCodePoint(nextCodePoint)) - { - _lexIdentifier(lexer); - return TokenType::Identifier; - } + // We treat all unicode characters as a part of an identifier. + if (isNonAsciiCodePoint(nextCodePoint)) + { + _lexIdentifier(lexer); + return TokenType::Identifier; + } - { - // If none of the above cases matched, then we have an - // unexpected/invalid character. + { + // If none of the above cases matched, then we have an + // unexpected/invalid character. - auto loc = _getSourceLoc(lexer); - int c = _advance(lexer); + auto loc = _getSourceLoc(lexer); + int c = _advance(lexer); - if (auto sink = lexer->getDiagnosticSink()) + if (auto sink = lexer->getDiagnosticSink()) + { + if (c >= 0x20 && c <= 0x7E) { - if(c >= 0x20 && c <= 0x7E) - { - char buffer[] = { (char) c, 0 }; - sink->diagnose(loc, LexerDiagnostics::illegalCharacterPrint, buffer); - } - else if(c == kEOF) - { - sink->diagnose(loc, LexerDiagnostics::unexpectedEndOfInput); - } - else - { - // Fallback: print as hexadecimal - sink->diagnose(loc, LexerDiagnostics::illegalCharacterHex, String((unsigned char)c, 16)); - } + char buffer[] = {(char)c, 0}; + sink->diagnose(loc, LexerDiagnostics::illegalCharacterPrint, buffer); + } + else if (c == kEOF) + { + sink->diagnose(loc, LexerDiagnostics::unexpectedEndOfInput); + } + else + { + // Fallback: print as hexadecimal + sink->diagnose( + loc, + LexerDiagnostics::illegalCharacterHex, + String((unsigned char)c, 16)); } - - return TokenType::Invalid; } + + return TokenType::Invalid; } +} - Token Lexer::lexToken() +Token Lexer::lexToken() +{ + for (;;) { - for(;;) - { - Token token; - token.loc = _getSourceLoc(this); + Token token; + token.loc = _getSourceLoc(this); - char const* textBegin = m_cursor; + char const* textBegin = m_cursor; - auto tokenType = _lexTokenImpl(this); + auto tokenType = _lexTokenImpl(this); - // The flags on the token we just lexed will be based - // on the current state of the lexer. - // - auto tokenFlags = m_tokenFlags; - // - // Depending on what kind of token we just lexed, the - // flags that will be used for the *next* token might - // need to be updated. - // - switch(tokenType) + // The flags on the token we just lexed will be based + // on the current state of the lexer. + // + auto tokenFlags = m_tokenFlags; + // + // Depending on what kind of token we just lexed, the + // flags that will be used for the *next* token might + // need to be updated. + // + switch (tokenType) + { + case TokenType::NewLine: { - case TokenType::NewLine: - { - // If we just reached the end of a line, then the next token - // should count as being at the start of a line, and also after - // whitespace. - // - m_tokenFlags = TokenFlag::AtStartOfLine | TokenFlag::AfterWhitespace; - break; - } + // If we just reached the end of a line, then the next token + // should count as being at the start of a line, and also after + // whitespace. + // + m_tokenFlags = TokenFlag::AtStartOfLine | TokenFlag::AfterWhitespace; + break; + } - case TokenType::WhiteSpace: - case TokenType::BlockComment: - case TokenType::LineComment: - { - // True horizontal whitespace and comments both count as whitespace. - // - // Note that a line comment does not include the terminating newline, - // we do not need to set `AtStartOfLine` here. - // - m_tokenFlags |= TokenFlag::AfterWhitespace; - break; - } - - default: - { - // If we read some token other then the above cases, then we are - // neither after whitespace nor at the start of a line. - // - m_tokenFlags = 0; - break; - } + case TokenType::WhiteSpace: + case TokenType::BlockComment: + case TokenType::LineComment: + { + // True horizontal whitespace and comments both count as whitespace. + // + // Note that a line comment does not include the terminating newline, + // we do not need to set `AtStartOfLine` here. + // + m_tokenFlags |= TokenFlag::AfterWhitespace; + break; + } + + default: + { + // If we read some token other then the above cases, then we are + // neither after whitespace nor at the start of a line. + // + m_tokenFlags = 0; + break; } + } - token.type = tokenType; - token.flags = tokenFlags; + token.type = tokenType; + token.flags = tokenFlags; - char const* textEnd = m_cursor; + char const* textEnd = m_cursor; - // Note(tfoley): `StringBuilder::Append()` seems to crash when appending zero bytes - if(textEnd != textBegin) + // Note(tfoley): `StringBuilder::Append()` seems to crash when appending zero bytes + if (textEnd != textBegin) + { + // "scrubbing" token value here to remove escaped newlines... + // + // Only perform this work if we encountered an escaped newline + // while lexing this token (e.g., keep a flag on the lexer), or + // do it on-demand when the actual value of the token is needed. + if (tokenFlags & TokenFlag::ScrubbingNeeded) { - // "scrubbing" token value here to remove escaped newlines... - // - // Only perform this work if we encountered an escaped newline - // while lexing this token (e.g., keep a flag on the lexer), or - // do it on-demand when the actual value of the token is needed. - if (tokenFlags & TokenFlag::ScrubbingNeeded) - { - // Allocate space that will always be more than enough for stripped contents - char* startDst = (char*)m_memoryArena->allocateUnaligned(textEnd - textBegin); - char* dst = startDst; + // Allocate space that will always be more than enough for stripped contents + char* startDst = (char*)m_memoryArena->allocateUnaligned(textEnd - textBegin); + char* dst = startDst; - auto tt = textBegin; - while (tt != textEnd) + auto tt = textBegin; + while (tt != textEnd) + { + char c = *tt++; + if (c == '\\') { - char c = *tt++; - if (c == '\\') + char d = *tt; + switch (d) { - char d = *tt; - switch (d) - { - case '\r': case '\n': + case '\r': + case '\n': { tt++; char e = *tt; @@ -1502,116 +1565,111 @@ namespace Slang } continue; - default: - break; - } + default: break; } - *dst++ = c; } - token.setContent(UnownedStringSlice(startDst, dst)); - } - else - { - token.setContent(UnownedStringSlice(textBegin, textEnd)); + *dst++ = c; } + token.setContent(UnownedStringSlice(startDst, dst)); } - - if (m_namePool) + else { - if (tokenType == TokenType::Identifier || tokenType == TokenType::CompletionRequest) - { - token.setName(m_namePool->getName(token.getContent())); - } + token.setContent(UnownedStringSlice(textBegin, textEnd)); } - - return token; } - } - TokenList Lexer::lexAllSemanticTokens() - { - TokenList tokenList; - for(;;) + if (m_namePool) { - Token token = lexToken(); - - // We are only interested intokens that are semantically - // significant, so we will skip over forms of whitespace - // and comments. - // - switch( token.type ) + if (tokenType == TokenType::Identifier || tokenType == TokenType::CompletionRequest) { - default: - break; - - case TokenType::WhiteSpace: - case TokenType::BlockComment: - case TokenType::LineComment: - case TokenType::NewLine: - continue; + token.setName(m_namePool->getName(token.getContent())); } - - tokenList.add(token); - if(token.type == TokenType::EndOfFile) - return tokenList; } + + return token; } +} - TokenList Lexer::lexAllMarkupTokens() +TokenList Lexer::lexAllSemanticTokens() +{ + TokenList tokenList; + for (;;) { - TokenList tokenList; - for(;;) - { - Token token = lexToken(); - switch( token.type ) - { - default: - break; + Token token = lexToken(); - case TokenType::WhiteSpace: - case TokenType::NewLine: - continue; - } + // We are only interested intokens that are semantically + // significant, so we will skip over forms of whitespace + // and comments. + // + switch (token.type) + { + default: break; - tokenList.add(token); - if(token.type == TokenType::EndOfFile) - return tokenList; + case TokenType::WhiteSpace: + case TokenType::BlockComment: + case TokenType::LineComment: + case TokenType::NewLine: continue; } + + tokenList.add(token); + if (token.type == TokenType::EndOfFile) + return tokenList; } +} - /* static */UnownedStringSlice Lexer::sourceLocationLexer(const UnownedStringSlice& in) +TokenList Lexer::lexAllMarkupTokens() +{ + TokenList tokenList; + for (;;) { - Lexer lexer; + Token token = lexToken(); + switch (token.type) + { + default: break; - SourceManager sourceManager; - sourceManager.initialize(nullptr, nullptr); + case TokenType::WhiteSpace: + case TokenType::NewLine: continue; + } - auto sourceFile = sourceManager.createSourceFileWithString(PathInfo::makeUnknown(), in); - auto sourceView = sourceManager.createSourceView(sourceFile, nullptr, SourceLoc::fromRaw(0)); + tokenList.add(token); + if (token.type == TokenType::EndOfFile) + return tokenList; + } +} - DiagnosticSink sink(&sourceManager, nullptr); +/* static */ UnownedStringSlice Lexer::sourceLocationLexer(const UnownedStringSlice& in) +{ + Lexer lexer; - MemoryArena arena; + SourceManager sourceManager; + sourceManager.initialize(nullptr, nullptr); - RootNamePool rootNamePool; - NamePool namePool; - namePool.setRootNamePool(&rootNamePool); + auto sourceFile = sourceManager.createSourceFileWithString(PathInfo::makeUnknown(), in); + auto sourceView = sourceManager.createSourceView(sourceFile, nullptr, SourceLoc::fromRaw(0)); - lexer.initialize(sourceView, &sink, &namePool, &arena); + DiagnosticSink sink(&sourceManager, nullptr); - Token tok = lexer.lexToken(); + MemoryArena arena; - if (tok.type == TokenType::Invalid) - { - return UnownedStringSlice(); - } + RootNamePool rootNamePool; + NamePool namePool; + namePool.setRootNamePool(&rootNamePool); - const int offset = sourceView->getRange().getOffset(tok.loc); + lexer.initialize(sourceView, &sink, &namePool, &arena); - SLANG_ASSERT(offset >= 0 && offset <= in.getLength()); - SLANG_ASSERT(Index(offset + tok.charsCount) <= in.getLength()); + Token tok = lexer.lexToken(); - return UnownedStringSlice(in.begin() + offset, in.begin() + offset + tok.charsCount); + if (tok.type == TokenType::Invalid) + { + return UnownedStringSlice(); } + const int offset = sourceView->getRange().getOffset(tok.loc); + + SLANG_ASSERT(offset >= 0 && offset <= in.getLength()); + SLANG_ASSERT(Index(offset + tok.charsCount) <= in.getLength()); + + return UnownedStringSlice(in.begin() + offset, in.begin() + offset + tok.charsCount); } + +} // namespace Slang diff --git a/source/compiler-core/slang-lexer.h b/source/compiler-core/slang-lexer.h index 3a2506d85..a9883ced6 100644 --- a/source/compiler-core/slang-lexer.h +++ b/source/compiler-core/slang-lexer.h @@ -6,173 +6,176 @@ namespace Slang { - struct NamePool; +struct NamePool; - // +// - struct TokenList - { - const Token* begin() const; - const Token* end() const; +struct TokenList +{ + const Token* begin() const; + const Token* end() const; - SLANG_FORCE_INLINE void add(const Token& token) { m_tokens.add(token); } + SLANG_FORCE_INLINE void add(const Token& token) { m_tokens.add(token); } - List m_tokens; - }; + List m_tokens; +}; - struct TokenSpan +struct TokenSpan +{ + TokenSpan(); + TokenSpan(TokenList const& tokenList) + : m_begin(tokenList.begin()), m_end(tokenList.end()) { - TokenSpan(); - TokenSpan( - TokenList const& tokenList) - : m_begin(tokenList.begin()) - , m_end (tokenList.end ()) - {} + } - const Token* begin() const { return m_begin; } - const Token* end () const { return m_end ; } + const Token* begin() const { return m_begin; } + const Token* end() const { return m_end; } - int getCount() { return (int)(m_end - m_begin); } + int getCount() { return (int)(m_end - m_begin); } - const Token* m_begin; - const Token* m_end; - }; + const Token* m_begin; + const Token* m_end; +}; - struct TokenReader +struct TokenReader +{ + Token m_nextToken; + TokenReader(); + explicit TokenReader(TokenSpan const& tokens) + : m_cursor(tokens.begin()), m_end(tokens.end()) { - Token m_nextToken; - TokenReader(); - explicit TokenReader(TokenSpan const& tokens) - : m_cursor(tokens.begin()) - , m_end (tokens.end ()) - { - _updateLookaheadToken(); - } - explicit TokenReader(TokenList const& tokens) - : m_cursor(tokens.begin()) - , m_end (tokens.end ()) - { - _updateLookaheadToken(); - } - explicit TokenReader(Token const* begin, Token const* end) - : m_cursor(begin) - , m_end (end) + _updateLookaheadToken(); + } + explicit TokenReader(TokenList const& tokens) + : m_cursor(tokens.begin()), m_end(tokens.end()) + { + _updateLookaheadToken(); + } + explicit TokenReader(Token const* begin, Token const* end) + : m_cursor(begin), m_end(end) + { + _updateLookaheadToken(); + } + struct ParsingCursor + { + bool operator==(const ParsingCursor& rhs) const { - _updateLookaheadToken(); + return tokenReaderCursor == rhs.tokenReaderCursor; } - struct ParsingCursor - { - bool operator==(const ParsingCursor& rhs) const { return tokenReaderCursor == rhs.tokenReaderCursor; } - bool operator!=(const ParsingCursor& rhs) const { return !(*this == rhs); } + bool operator!=(const ParsingCursor& rhs) const { return !(*this == rhs); } - bool isValid() const { return tokenReaderCursor != nullptr; } + bool isValid() const { return tokenReaderCursor != nullptr; } - Token nextToken; - const Token* tokenReaderCursor = nullptr; - }; - ParsingCursor getCursor() - { - ParsingCursor rs; - rs.nextToken = m_nextToken; - rs.tokenReaderCursor = m_cursor; - return rs; - } - void setCursor(ParsingCursor cursor) - { - m_cursor = cursor.tokenReaderCursor; - m_nextToken = cursor.nextToken; - } - bool isAtCursor(const ParsingCursor& cursor) const - { - return cursor.tokenReaderCursor == m_cursor; - } - bool isAtEnd() const { return m_cursor == m_end; } - Token& peekToken(); - TokenType peekTokenType() const; - SourceLoc peekLoc() const; + Token nextToken; + const Token* tokenReaderCursor = nullptr; + }; + ParsingCursor getCursor() + { + ParsingCursor rs; + rs.nextToken = m_nextToken; + rs.tokenReaderCursor = m_cursor; + return rs; + } + void setCursor(ParsingCursor cursor) + { + m_cursor = cursor.tokenReaderCursor; + m_nextToken = cursor.nextToken; + } + bool isAtCursor(const ParsingCursor& cursor) const + { + return cursor.tokenReaderCursor == m_cursor; + } + bool isAtEnd() const { return m_cursor == m_end; } + Token& peekToken(); + TokenType peekTokenType() const; + SourceLoc peekLoc() const; - Token advanceToken(); + Token advanceToken(); - int getCount() { return (int)(m_end - m_cursor); } + int getCount() { return (int)(m_end - m_cursor); } - const Token* m_cursor; - const Token* m_end; - static Token getEndOfFileToken(); + const Token* m_cursor; + const Token* m_end; + static Token getEndOfFileToken(); - private: - /// Update the lookahead token in `m_nextToken` to reflect the cursor state - void _updateLookaheadToken(); - }; +private: + /// Update the lookahead token in `m_nextToken` to reflect the cursor state + void _updateLookaheadToken(); +}; - typedef unsigned int LexerFlags; - enum - { - kLexerFlag_SuppressDiagnostics = 1 << 2, ///< Suppress errors about invalid/unsupported characters - }; +typedef unsigned int LexerFlags; +enum +{ + kLexerFlag_SuppressDiagnostics = 1 + << 2, ///< Suppress errors about invalid/unsupported characters +}; - struct Lexer +struct Lexer +{ + void initialize( + SourceView* sourceView, + DiagnosticSink* sink, + NamePool* namePool, + MemoryArena* memoryArena); + + ~Lexer(); + + /// Runs the lexer to try and extract a single token, which is returned. + /// This can be used by the DiagnosticSink to be able to display more appropriate + /// information when displaying a source location - such as underscoring the + /// token at that location. + /// + /// NOTE! This function is relatively slow, and is designed for use around this specific + /// purpose. It does not return a token or a token type, because that information is + /// not needed by the DiagnosticSink. + static UnownedStringSlice sourceLocationLexer(const UnownedStringSlice& in); + + /// Lex the next token in the input stream, returning an EOF token if at end. + Token lexToken(); + + /// Lex all tokens (up to the end of the stream) that are semantically relevant + TokenList lexAllSemanticTokens(); + + /// Lex all tokens (up to the end of the stream) that are relevant to things like markup + TokenList lexAllMarkupTokens(); + + /// Get the diagnostic sink, taking into account flags. Will return null if suppressing + /// diagnostics. + DiagnosticSink* getDiagnosticSink() { - void initialize( - SourceView* sourceView, - DiagnosticSink* sink, - NamePool* namePool, - MemoryArena* memoryArena); - - ~Lexer(); - - /// Runs the lexer to try and extract a single token, which is returned. - /// This can be used by the DiagnosticSink to be able to display more appropriate - /// information when displaying a source location - such as underscoring the - /// token at that location. - /// - /// NOTE! This function is relatively slow, and is designed for use around this specific - /// purpose. It does not return a token or a token type, because that information is - /// not needed by the DiagnosticSink. - static UnownedStringSlice sourceLocationLexer(const UnownedStringSlice& in); - - /// Lex the next token in the input stream, returning an EOF token if at end. - Token lexToken(); - - /// Lex all tokens (up to the end of the stream) that are semantically relevant - TokenList lexAllSemanticTokens(); - - /// Lex all tokens (up to the end of the stream) that are relevant to things like markup - TokenList lexAllMarkupTokens(); - - /// Get the diagnostic sink, taking into account flags. Will return null if suppressing diagnostics. - DiagnosticSink* getDiagnosticSink() - { - return ((m_lexerFlags & kLexerFlag_SuppressDiagnostics) == 0) ? m_sink : nullptr; - } + return ((m_lexerFlags & kLexerFlag_SuppressDiagnostics) == 0) ? m_sink : nullptr; + } - SourceView* m_sourceView; - DiagnosticSink* m_sink; - NamePool* m_namePool; + SourceView* m_sourceView; + DiagnosticSink* m_sink; + NamePool* m_namePool; - char const* m_cursor; + char const* m_cursor; - char const* m_begin; - char const* m_end; + char const* m_begin; + char const* m_end; - /// The starting sourceLoc (same as first location of SourceView) - SourceLoc m_startLoc; + /// The starting sourceLoc (same as first location of SourceView) + SourceLoc m_startLoc; - TokenFlags m_tokenFlags; - LexerFlags m_lexerFlags; + TokenFlags m_tokenFlags; + LexerFlags m_lexerFlags; + + MemoryArena* m_memoryArena; +}; - MemoryArena* m_memoryArena; - }; - - // Helper routines for extracting values from tokens - String getStringLiteralTokenValue(Token const& token); - String getFileNameTokenValue(Token const& token); +// Helper routines for extracting values from tokens +String getStringLiteralTokenValue(Token const& token); +String getFileNameTokenValue(Token const& token); - typedef int64_t IntegerLiteralValue; - typedef double FloatingPointLiteralValue; +typedef int64_t IntegerLiteralValue; +typedef double FloatingPointLiteralValue; - IntegerLiteralValue getIntegerLiteralValue(Token const& token, UnownedStringSlice* outSuffix = 0); - FloatingPointLiteralValue getFloatingPointLiteralValue(Token const& token, UnownedStringSlice* outSuffix = 0); -} +IntegerLiteralValue getIntegerLiteralValue(Token const& token, UnownedStringSlice* outSuffix = 0); +FloatingPointLiteralValue getFloatingPointLiteralValue( + Token const& token, + UnownedStringSlice* outSuffix = 0); +} // namespace Slang #endif diff --git a/source/compiler-core/slang-llvm-compiler.cpp b/source/compiler-core/slang-llvm-compiler.cpp index 3d24d3aa1..457268b98 100644 --- a/source/compiler-core/slang-llvm-compiler.cpp +++ b/source/compiler-core/slang-llvm-compiler.cpp @@ -6,11 +6,15 @@ namespace Slang { -/* static */SlangResult LLVMDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +/* static */ SlangResult LLVMDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) { ComPtr library; - SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, "slang-llvm", library)); + SLANG_RETURN_ON_FAIL( + DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, "slang-llvm", library)); SLANG_ASSERT(library); if (!library) @@ -18,14 +22,17 @@ namespace Slang return SLANG_FAIL; } - typedef SlangResult(*CreateDownstreamCompilerFunc)(const Guid& intf, IDownstreamCompiler** outCompiler); + typedef SlangResult ( + *CreateDownstreamCompilerFunc)(const Guid& intf, IDownstreamCompiler** outCompiler); ComPtr downstreamCompiler; // Only accept V4, so we can update IArtifact without breaking anything - if (auto fnV4 = (CreateDownstreamCompilerFunc)library->findFuncByName("createLLVMDownstreamCompiler_V4")) + if (auto fnV4 = (CreateDownstreamCompilerFunc)library->findFuncByName( + "createLLVMDownstreamCompiler_V4")) { - SLANG_RETURN_ON_FAIL(fnV4(IDownstreamCompiler::getTypeGuid(), downstreamCompiler.writeRef())); + SLANG_RETURN_ON_FAIL( + fnV4(IDownstreamCompiler::getTypeGuid(), downstreamCompiler.writeRef())); } else { @@ -37,4 +44,4 @@ namespace Slang return SLANG_OK; } -} +} // namespace Slang diff --git a/source/compiler-core/slang-llvm-compiler.h b/source/compiler-core/slang-llvm-compiler.h index a05e1fed9..298d9a0ad 100644 --- a/source/compiler-core/slang-llvm-compiler.h +++ b/source/compiler-core/slang-llvm-compiler.h @@ -1,18 +1,20 @@ #ifndef SLANG_LLVM_COMPILER_UTIL_H #define SLANG_LLVM_COMPILER_UTIL_H -#include "slang-downstream-compiler-util.h" - #include "../core/slang-platform.h" +#include "slang-downstream-compiler-util.h" namespace Slang { struct LLVMDownstreamCompilerUtil { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-metal-compiler.cpp b/source/compiler-core/slang-metal-compiler.cpp index f8639b763..af455a0f7 100644 --- a/source/compiler-core/slang-metal-compiler.cpp +++ b/source/compiler-core/slang-metal-compiler.cpp @@ -1,102 +1,111 @@ #include "slang-metal-compiler.h" -#include "slang-gcc-compiler-util.h" + #include "slang-artifact-desc-util.h" -#include "slang-artifact-util.h" #include "slang-artifact-representation.h" +#include "slang-artifact-util.h" +#include "slang-gcc-compiler-util.h" namespace Slang { - class MetalDownstreamCompiler : public DownstreamCompilerBase +class MetalDownstreamCompiler : public DownstreamCompilerBase +{ +public: + // Because the metal compiler shares the same commandline interface with clang, + // we will use GccDownstreamCompilerUtil, which implements both gcc and clang, + // to create the inner compiler and wrap it here. + // + ComPtr cppCompiler; + String executablePath; + + MetalDownstreamCompiler(ComPtr& innerCompiler, String path) + : DownstreamCompilerBase(innerCompiler->getDesc()) + , cppCompiler(innerCompiler) + , executablePath(path) { - public: - // Because the metal compiler shares the same commandline interface with clang, - // we will use GccDownstreamCompilerUtil, which implements both gcc and clang, - // to create the inner compiler and wrap it here. - // - ComPtr cppCompiler; - String executablePath; - - MetalDownstreamCompiler(ComPtr& innerCompiler, String path) - : DownstreamCompilerBase(innerCompiler->getDesc()) - , cppCompiler(innerCompiler) - , executablePath(path) - { - } - - virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() override { return true; } - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) override - { - // All compile requests should be routed directly to the inner compiler. - return cppCompiler->compile(options, outArtifact); - } - - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert(const ArtifactDesc& from, const ArtifactDesc& to) override - { - // Report that we can convert Metal IR to disassembly. - return ArtifactDescUtil::isDisassembly(from, to) && from.payload == ArtifactPayload::MetalAIR; - } - - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) override - { - // Use metal-objdump to disassemble the Metal IR. - - ExecutableLocation exeLocation(executablePath, "metal-objdump"); - CommandLine cmdLine; - cmdLine.setExecutableLocation(exeLocation); - cmdLine.addArg("--disassemble"); - ComPtr srcFile; - SLANG_RETURN_ON_FAIL(from->requireFile(IArtifact::Keep::No, srcFile.writeRef())); - cmdLine.addArg(String(srcFile->getPath())); - - ExecuteResult exeRes; - SLANG_RETURN_ON_FAIL(ProcessUtil::execute(cmdLine, exeRes)); - auto artifact = ArtifactUtil::createArtifact(to); - artifact->addRepresentationUnknown(StringBlob::create(exeRes.standardOutput)); - *outArtifact = artifact.detach(); - return SLANG_OK; - } - }; - - static SlangResult locateMetalCompiler(const String& path, DownstreamCompilerSet* set) + } + + virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() override { return true; } + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outArtifact) override { - ComPtr innerCppCompiler; - - ExecutableLocation metalcLocation = ExecutableLocation(path, "metal"); - - String metalSDKPath = path; - -#if defined (SLANG_APPLE_FAMILY) - // Use xcrun command to find the metal compiler. - CommandLine xcrunCmdLine; - ExecutableLocation xcrunLocation("xcrun"); - xcrunCmdLine.setExecutableLocation(xcrunLocation); - xcrunCmdLine.addArg("--sdk"); - xcrunCmdLine.addArg("macosx"); - xcrunCmdLine.addArg("--find"); - xcrunCmdLine.addArg("metal"); - ExecuteResult exeRes; - if (SLANG_SUCCEEDED(ProcessUtil::execute(xcrunCmdLine, exeRes))) - { - String metalPath = exeRes.standardOutput.trim(); - metalcLocation = ExecutableLocation(ExecutableLocation::Type::Path, metalPath); - metalSDKPath = Path::getParentDirectory(metalcLocation.m_pathOrName); - } -#endif + // All compile requests should be routed directly to the inner compiler. + return cppCompiler->compile(options, outArtifact); + } - SLANG_RETURN_ON_FAIL(GCCDownstreamCompilerUtil::createCompiler(metalcLocation, innerCppCompiler)); + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) override + { + // Report that we can convert Metal IR to disassembly. + return ArtifactDescUtil::isDisassembly(from, to) && + from.payload == ArtifactPayload::MetalAIR; + } + + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) override + { + // Use metal-objdump to disassemble the Metal IR. - ComPtr compiler = ComPtr( - new MetalDownstreamCompiler(innerCppCompiler, metalSDKPath)); - set->addCompiler(compiler); + ExecutableLocation exeLocation(executablePath, "metal-objdump"); + CommandLine cmdLine; + cmdLine.setExecutableLocation(exeLocation); + cmdLine.addArg("--disassemble"); + ComPtr srcFile; + SLANG_RETURN_ON_FAIL(from->requireFile(IArtifact::Keep::No, srcFile.writeRef())); + cmdLine.addArg(String(srcFile->getPath())); + + ExecuteResult exeRes; + SLANG_RETURN_ON_FAIL(ProcessUtil::execute(cmdLine, exeRes)); + auto artifact = ArtifactUtil::createArtifact(to); + artifact->addRepresentationUnknown(StringBlob::create(exeRes.standardOutput)); + *outArtifact = artifact.detach(); return SLANG_OK; } +}; - SlangResult MetalDownstreamCompilerUtil::locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set) +static SlangResult locateMetalCompiler(const String& path, DownstreamCompilerSet* set) +{ + ComPtr innerCppCompiler; + + ExecutableLocation metalcLocation = ExecutableLocation(path, "metal"); + + String metalSDKPath = path; + +#if defined(SLANG_APPLE_FAMILY) + // Use xcrun command to find the metal compiler. + CommandLine xcrunCmdLine; + ExecutableLocation xcrunLocation("xcrun"); + xcrunCmdLine.setExecutableLocation(xcrunLocation); + xcrunCmdLine.addArg("--sdk"); + xcrunCmdLine.addArg("macosx"); + xcrunCmdLine.addArg("--find"); + xcrunCmdLine.addArg("metal"); + ExecuteResult exeRes; + if (SLANG_SUCCEEDED(ProcessUtil::execute(xcrunCmdLine, exeRes))) { - SLANG_UNUSED(loader); - return locateMetalCompiler(path, set); + String metalPath = exeRes.standardOutput.trim(); + metalcLocation = ExecutableLocation(ExecutableLocation::Type::Path, metalPath); + metalSDKPath = Path::getParentDirectory(metalcLocation.m_pathOrName); } +#endif + + SLANG_RETURN_ON_FAIL( + GCCDownstreamCompilerUtil::createCompiler(metalcLocation, innerCppCompiler)); + + ComPtr compiler = + ComPtr(new MetalDownstreamCompiler(innerCppCompiler, metalSDKPath)); + set->addCompiler(compiler); + return SLANG_OK; +} +SlangResult MetalDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) +{ + SLANG_UNUSED(loader); + return locateMetalCompiler(path, set); } + +} // namespace Slang diff --git a/source/compiler-core/slang-metal-compiler.h b/source/compiler-core/slang-metal-compiler.h index 7a14e5fa9..b311a3ea2 100644 --- a/source/compiler-core/slang-metal-compiler.h +++ b/source/compiler-core/slang-metal-compiler.h @@ -1,18 +1,20 @@ #ifndef SLANG_METAL_COMPILER_UTIL_H #define SLANG_METAL_COMPILER_UTIL_H -#include "slang-downstream-compiler-util.h" - #include "../core/slang-platform.h" +#include "slang-downstream-compiler-util.h" namespace Slang { - struct MetalDownstreamCompilerUtil - { - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); - }; +struct MetalDownstreamCompilerUtil +{ + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); +}; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-misc-diagnostic-defs.h b/source/compiler-core/slang-misc-diagnostic-defs.h index a2ccc4657..984a3a017 100644 --- a/source/compiler-core/slang-misc-diagnostic-defs.h +++ b/source/compiler-core/slang-misc-diagnostic-defs.h @@ -14,7 +14,7 @@ // for any arguments. #ifndef DIAGNOSTIC -#error Need to #define DIAGNOSTIC(...) before including +#error Need to #define DIAGNOSTIC(...) before including #define DIAGNOSTIC(id, severity, name, messageFormat) /* */ #endif @@ -24,15 +24,39 @@ DIAGNOSTIC(-1, Note, seeTokenPasteLocation, "see token pasted location") -DIAGNOSTIC(100000, Error, downstreamNameNotKnown, "downstream tool name not known, allowed names are $0") -DIAGNOSTIC(100001, Error, expectedArgumentForOption, "expected an argument for command-line option '$0'") +DIAGNOSTIC( + 100000, + Error, + downstreamNameNotKnown, + "downstream tool name not known, allowed names are $0") +DIAGNOSTIC( + 100001, + Error, + expectedArgumentForOption, + "expected an argument for command-line option '$0'") DIAGNOSTIC(100002, Error, unbalancedDownstreamArguments, "unbalanced downstream arguments") -DIAGNOSTIC(100003, Error, closeOfUnopenDownstreamArgs, "close of an unopen downstream argument scope") +DIAGNOSTIC( + 100003, + Error, + closeOfUnopenDownstreamArgs, + "close of an unopen downstream argument scope") DIAGNOSTIC(100004, Error, downstreamToolNameNotDefined, "downstream tool name not defined") -DIAGNOSTIC(100005, Error, invalidArgumentForOption, "invalid argument format for command-line option '$0'") - -DIAGNOSTIC(99999, Note, noteLocationOfInternalError, "an internal error threw an exception while working on code near this location") - -DIAGNOSTIC(29104, Error, spirvCoreGrammarJSONParseFailure, "unexpected JSON in spirv core grammar file: $0") +DIAGNOSTIC( + 100005, + Error, + invalidArgumentForOption, + "invalid argument format for command-line option '$0'") + +DIAGNOSTIC( + 99999, + Note, + noteLocationOfInternalError, + "an internal error threw an exception while working on code near this location") + +DIAGNOSTIC( + 29104, + Error, + spirvCoreGrammarJSONParseFailure, + "unexpected JSON in spirv core grammar file: $0") #undef DIAGNOSTIC diff --git a/source/compiler-core/slang-name-convention-util.cpp b/source/compiler-core/slang-name-convention-util.cpp index c3d08326c..cb44aa10e 100644 --- a/source/compiler-core/slang-name-convention-util.cpp +++ b/source/compiler-core/slang-name-convention-util.cpp @@ -7,14 +7,15 @@ namespace Slang { -/* static */NameConvention NameConventionUtil::inferConventionFromText(const UnownedStringSlice& slice) +/* static */ NameConvention NameConventionUtil::inferConventionFromText( + const UnownedStringSlice& slice) { // If no chars, or first char isn't alpha we don't know what it is if (slice.getLength() <= 0 || !CharUtil::isAlpha(slice[0])) { return NameConvention::Invalid; } - + typedef int Flags; struct Flag { @@ -33,9 +34,9 @@ namespace Slang { switch (c) { - case '-': flags |= Flag::Dash; break; - case '_': flags |= Flag::Underscore; break; - default: + case '-': flags |= Flag::Dash; break; + case '_': flags |= Flag::Underscore; break; + default: { if (CharUtil::isLower(c)) { @@ -61,62 +62,66 @@ namespace Slang // Use flags to determine what convention is used switch (flags) { - // We'll assume it's lower camel. - case Flag::Lower: return NameConvention::LowerCamel; - // We'll assume it's upper snake. It almost certainly isn't camel, and snake is more usual - // than kabab. - case Flag::Upper: return NameConvention::UpperSnake; - case Flag::Upper | Flag::Lower: + // We'll assume it's lower camel. + case Flag::Lower: return NameConvention::LowerCamel; + // We'll assume it's upper snake. It almost certainly isn't camel, and snake is more usual + // than kabab. + case Flag::Upper: return NameConvention::UpperSnake; + case Flag::Upper | Flag::Lower: { // Looks like camel, choose the right case based on first char - return CharUtil::isUpper(slice[0]) ? NameConvention::UpperCamel : NameConvention::LowerCamel; + return CharUtil::isUpper(slice[0]) ? NameConvention::UpperCamel + : NameConvention::LowerCamel; } - case Flag::Lower | Flag::Dash: return NameConvention::LowerKabab; - case Flag::Upper | Flag::Dash: return NameConvention::UpperKabab; - case Flag::Lower | Flag::Underscore: return NameConvention::LowerSnake; - case Flag::Upper | Flag::Underscore: return NameConvention::UpperSnake; - default: break; + case Flag::Lower | Flag::Dash: return NameConvention::LowerKabab; + case Flag::Upper | Flag::Dash: return NameConvention::UpperKabab; + case Flag::Lower | Flag::Underscore: return NameConvention::LowerSnake; + case Flag::Upper | Flag::Underscore: return NameConvention::UpperSnake; + default: break; } // Don't know what this style is return NameConvention::Invalid; } -/* static */NameStyle NameConventionUtil::inferStyleFromText(const UnownedStringSlice& slice) +/* static */ NameStyle NameConventionUtil::inferStyleFromText(const UnownedStringSlice& slice) { for (const char c : slice) { switch (c) { - case '-': return NameStyle::Kabab; - case '_': return NameStyle::Snake; - default: break; + case '-': return NameStyle::Kabab; + case '_': return NameStyle::Snake; + default: break; } } return NameStyle::Camel; } -/* static */void NameConventionUtil::split(NameStyle style, const UnownedStringSlice& slice, List& out) +/* static */ void NameConventionUtil::split( + NameStyle style, + const UnownedStringSlice& slice, + List& out) { switch (style) { - case NameStyle::Kabab: + case NameStyle::Kabab: { StringUtil::split(slice, '-', out); break; } - case NameStyle::Snake: + case NameStyle::Snake: { StringUtil::split(slice, '_', out); break; } - case NameStyle::Camel: + case NameStyle::Camel: { typedef CharUtil::Flags CharFlags; typedef CharUtil::Flag CharFlag; CharFlags prevFlags = 0; - const char*const end = slice.end(); + const char* const end = slice.end(); const char* start = slice.begin(); for (const char* cur = start; cur < end; ++cur) @@ -134,15 +139,18 @@ namespace Slang } else if ((prevFlags & CharFlag::Upper) && cur + 1 < end) { - // This works with capital or uncapitalized acronyms, but if we have two capitalized acronyms following each other - it can't split. - // - // For example + // This works with capital or uncapitalized acronyms, but if we have two + // capitalized acronyms following each other - it can't split. + // + // For example // "IAABBSystem" -> "IAABB", "System" - // - // If it only accepted lower case acronyms the logic could be changed such that the following could be produced - // "IAabbSystem" -> "I", "Aabb", "System" // - // Since Slang source largely goes with upper case acronyms, we work with the heuristic here.. + // If it only accepted lower case acronyms the logic could be changed such + // that the following could be produced "IAabbSystem" -> "I", "Aabb", + // "System" + // + // Since Slang source largely goes with upper case acronyms, we work with + // the heuristic here.. if (CharUtil::isLower(cur[1])) { @@ -151,7 +159,7 @@ namespace Slang } } } - + prevFlags = flags; } @@ -162,7 +170,7 @@ namespace Slang } break; } - case NameStyle::Unknown: + case NameStyle::Unknown: { out.add(slice); break; @@ -175,7 +183,12 @@ void NameConventionUtil::split(const UnownedStringSlice& slice, List 0) { @@ -226,15 +239,19 @@ void NameConventionUtil::split(const UnownedStringSlice& slice, List slices; @@ -286,10 +307,12 @@ void NameConventionUtil::split(const UnownedStringSlice& slice, List& out); + /// Given a slice and a naming convention, split into it's constituent parts. If convention + /// isn't specified, will infer from slice using getConvention. + static void split( + NameStyle nameStyle, + const UnownedStringSlice& slice, + List& out); static void split(const UnownedStringSlice& slice, List& out); - /// Given slices, join together with the specified convention into out - static void join(const UnownedStringSlice* slices, Index slicesCount, NameConvention convention, StringBuilder& out); - - /// Join with a join char, and potentially changing case of input slices - static void join(const UnownedStringSlice* slices, Index slicesCount, NameConvention convention, char joinChar, StringBuilder& out); - - /// Convert from one convention to another. If fromConvention isn't specified, will infer from slice using getConvention. - static void convert(NameStyle fromStyle, const UnownedStringSlice& slice, NameConvention toConvention, StringBuilder& out); - static void convert(const UnownedStringSlice& slice, NameConvention toConvention, StringBuilder& out); + /// Given slices, join together with the specified convention into out + static void join( + const UnownedStringSlice* slices, + Index slicesCount, + NameConvention convention, + StringBuilder& out); + + /// Join with a join char, and potentially changing case of input slices + static void join( + const UnownedStringSlice* slices, + Index slicesCount, + NameConvention convention, + char joinChar, + StringBuilder& out); + + /// Convert from one convention to another. If fromConvention isn't specified, will infer from + /// slice using getConvention. + static void convert( + NameStyle fromStyle, + const UnownedStringSlice& slice, + NameConvention toConvention, + StringBuilder& out); + static void convert( + const UnownedStringSlice& slice, + NameConvention toConvention, + StringBuilder& out); }; -} +} // namespace Slang #endif // SLANG_COMPILER_CORE_NAME_CONVENTION_UTIL_H diff --git a/source/compiler-core/slang-name.cpp b/source/compiler-core/slang-name.cpp index c815b8aa8..6f79d25b5 100644 --- a/source/compiler-core/slang-name.cpp +++ b/source/compiler-core/slang-name.cpp @@ -1,11 +1,13 @@ // slang-name.cpp #include "slang-name.h" -namespace Slang { +namespace Slang +{ String getText(Name* name) { - if (!name) return String(); + if (!name) + return String(); return name->text; } diff --git a/source/compiler-core/slang-name.h b/source/compiler-core/slang-name.h index f8c1201af..331086d77 100644 --- a/source/compiler-core/slang-name.h +++ b/source/compiler-core/slang-name.h @@ -7,7 +7,8 @@ #include "../core/slang-basic.h" -namespace Slang { +namespace Slang +{ // The `Name` type is used to represent the name of a type, variable, etc. // @@ -36,7 +37,7 @@ public: // (e.g., so that it can be printed). String getText(Name* name); -/// Get the text as unowned string slice +/// Get the text as unowned string slice UnownedStringSlice getUnownedStringSliceText(Name* name); // Get a name as a C style string, or nullptr if name is nullptr @@ -50,7 +51,7 @@ const char* getCstr(Name* name); struct RootNamePool { // The mapping from text strings to the corresponding name. - Dictionary > names; + Dictionary> names; }; // A `NamePool` is effectively a way of storing a subset of the @@ -74,10 +75,7 @@ struct NamePool // If the name does not exist, return nullptr Name* tryGetName(String const& text); // Set the parent name pool to use for lookup - void setRootNamePool(RootNamePool* rootNamePool) - { - this->rootPool = rootNamePool; - } + void setRootNamePool(RootNamePool* rootNamePool) { this->rootPool = rootNamePool; } // diff --git a/source/compiler-core/slang-nvrtc-compiler.cpp b/source/compiler-core/slang-nvrtc-compiler.cpp index 8e234e634..2a4597ddc 100644 --- a/source/compiler-core/slang-nvrtc-compiler.cpp +++ b/source/compiler-core/slang-nvrtc-compiler.cpp @@ -1,45 +1,40 @@ // slang-nvrtc-compiler.cpp #include "slang-nvrtc-compiler.h" -#include "../core/slang-common.h" -#include "slang-com-helper.h" - #include "../core/slang-blob.h" - -#include "../core/slang-string-util.h" -#include "../core/slang-string-slice-pool.h" - +#include "../core/slang-char-util.h" +#include "../core/slang-common.h" #include "../core/slang-io.h" -#include "../core/slang-shared-library.h" #include "../core/slang-semantic-version.h" - #include "../core/slang-shared-library.h" -#include "../core/slang-char-util.h" - +#include "../core/slang-string-slice-pool.h" +#include "../core/slang-string-util.h" +#include "slang-artifact-associated-impl.h" +#include "slang-artifact-desc-util.h" #include "slang-artifact-diagnostic-util.h" #include "slang-artifact-util.h" -#include "slang-artifact-desc-util.h" -#include "slang-artifact-associated-impl.h" +#include "slang-com-helper.h" namespace nvrtc { -typedef enum { - NVRTC_SUCCESS = 0, - NVRTC_ERROR_OUT_OF_MEMORY = 1, - NVRTC_ERROR_PROGRAM_CREATION_FAILURE = 2, - NVRTC_ERROR_INVALID_INPUT = 3, - NVRTC_ERROR_INVALID_PROGRAM = 4, - NVRTC_ERROR_INVALID_OPTION = 5, - NVRTC_ERROR_COMPILATION = 6, - NVRTC_ERROR_BUILTIN_OPERATION_FAILURE = 7, - NVRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION = 8, - NVRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION = 9, - NVRTC_ERROR_NAME_EXPRESSION_NOT_VALID = 10, - NVRTC_ERROR_INTERNAL_ERROR = 11 +typedef enum +{ + NVRTC_SUCCESS = 0, + NVRTC_ERROR_OUT_OF_MEMORY = 1, + NVRTC_ERROR_PROGRAM_CREATION_FAILURE = 2, + NVRTC_ERROR_INVALID_INPUT = 3, + NVRTC_ERROR_INVALID_PROGRAM = 4, + NVRTC_ERROR_INVALID_OPTION = 5, + NVRTC_ERROR_COMPILATION = 6, + NVRTC_ERROR_BUILTIN_OPERATION_FAILURE = 7, + NVRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION = 8, + NVRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION = 9, + NVRTC_ERROR_NAME_EXPRESSION_NOT_VALID = 10, + NVRTC_ERROR_INTERNAL_ERROR = 11 } nvrtcResult; -typedef struct _nvrtcProgram *nvrtcProgram; +typedef struct _nvrtcProgram* nvrtcProgram; // clang-format off #define SLANG_NVRTC_FUNCS(x) \ @@ -66,37 +61,37 @@ static SlangResult _asResult(nvrtcResult res) { switch (res) { - case NVRTC_SUCCESS: + case NVRTC_SUCCESS: { return SLANG_OK; } - case NVRTC_ERROR_OUT_OF_MEMORY: + case NVRTC_ERROR_OUT_OF_MEMORY: { return SLANG_E_OUT_OF_MEMORY; } - case NVRTC_ERROR_PROGRAM_CREATION_FAILURE: - case NVRTC_ERROR_INVALID_INPUT: - case NVRTC_ERROR_INVALID_PROGRAM: + case NVRTC_ERROR_PROGRAM_CREATION_FAILURE: + case NVRTC_ERROR_INVALID_INPUT: + case NVRTC_ERROR_INVALID_PROGRAM: { return SLANG_FAIL; } - case NVRTC_ERROR_INVALID_OPTION: + case NVRTC_ERROR_INVALID_OPTION: { return SLANG_E_INVALID_ARG; } - case NVRTC_ERROR_COMPILATION: - case NVRTC_ERROR_BUILTIN_OPERATION_FAILURE: - case NVRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION: - case NVRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION: - case NVRTC_ERROR_NAME_EXPRESSION_NOT_VALID: + case NVRTC_ERROR_COMPILATION: + case NVRTC_ERROR_BUILTIN_OPERATION_FAILURE: + case NVRTC_ERROR_NO_NAME_EXPRESSIONS_AFTER_COMPILATION: + case NVRTC_ERROR_NO_LOWERED_NAMES_BEFORE_COMPILATION: + case NVRTC_ERROR_NAME_EXPRESSION_NOT_VALID: { return SLANG_FAIL; } - case NVRTC_ERROR_INTERNAL_ERROR: + case NVRTC_ERROR_INTERNAL_ERROR: { return SLANG_E_INTERNAL_FAIL; } - default: return SLANG_FAIL; + default: return SLANG_FAIL; } } @@ -106,29 +101,27 @@ public: typedef DownstreamCompilerBase Super; // IDownstreamCompiler - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outArtifact) SLANG_OVERRIDE; virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; } - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; - /// Must be called before use + /// Must be called before use SlangResult init(ISlangSharedLibrary* library); NVRTCDownstreamCompiler() {} - -protected: +protected: struct ScopeProgram { - ScopeProgram(NVRTCDownstreamCompiler* compiler, nvrtcProgram program): - m_compiler(compiler), - m_program(program) - { - } - ~ScopeProgram() + ScopeProgram(NVRTCDownstreamCompiler* compiler, nvrtcProgram program) + : m_compiler(compiler), m_program(program) { - m_compiler->m_nvrtcDestroyProgram(&m_program); } + ~ScopeProgram() { m_compiler->m_nvrtcDestroyProgram(&m_program); } NVRTCDownstreamCompiler* m_compiler; nvrtcProgram m_program; }; @@ -139,8 +132,7 @@ protected: SlangResult _maybeAddHalfSupport(const CompileOptions& options, CommandLine& ioCmdLine); -#define SLANG_NVTRC_MEMBER_FUNCS(ret, name, params) \ - ret (*m_##name) params; +#define SLANG_NVTRC_MEMBER_FUNCS(ret, name, params) ret(*m_##name) params; SLANG_NVRTC_FUNCS(SLANG_NVTRC_MEMBER_FUNCS); @@ -148,19 +140,25 @@ protected: List m_cudaFp16FoundPaths; bool m_includeSearched = false; - // Holds location of where include (for cuda_fp16.h) is found. + // Holds location of where include (for cuda_fp16.h) is found. String m_includePath; - ComPtr m_sharedLibrary; + ComPtr m_sharedLibrary; }; -#define SLANG_NVRTC_RETURN_ON_FAIL(x) { nvrtcResult _res = x; if (_res != NVRTC_SUCCESS) return _asResult(_res); } +#define SLANG_NVRTC_RETURN_ON_FAIL(x) \ + { \ + nvrtcResult _res = x; \ + if (_res != NVRTC_SUCCESS) \ + return _asResult(_res); \ + } SlangResult NVRTCDownstreamCompiler::init(ISlangSharedLibrary* library) { -#define SLANG_NVTRC_GET_FUNC(ret, name, params) \ - m_##name = (ret (*) params)library->findFuncByName(#name); \ - if (m_##name == nullptr) return SLANG_FAIL; +#define SLANG_NVTRC_GET_FUNC(ret, name, params) \ + m_##name = (ret(*) params)library->findFuncByName(#name); \ + if (m_##name == nullptr) \ + return SLANG_FAIL; SLANG_NVRTC_FUNCS(SLANG_NVTRC_GET_FUNC) @@ -174,7 +172,10 @@ SlangResult NVRTCDownstreamCompiler::init(ISlangSharedLibrary* library) return SLANG_OK; } -static SlangResult _parseLocation(SliceAllocator& allocator, const UnownedStringSlice& in, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseLocation( + SliceAllocator& allocator, + const UnownedStringSlice& in, + ArtifactDiagnostic& outDiagnostic) { const Index startIndex = in.indexOf('('); @@ -184,7 +185,8 @@ static SlangResult _parseLocation(SliceAllocator& allocator, const UnownedString UnownedStringSlice remaining(in.begin() + startIndex + 1, in.end()); const Int endIndex = remaining.indexOf(')'); - UnownedStringSlice lineText = UnownedStringSlice(remaining.begin(), remaining.begin() + endIndex); + UnownedStringSlice lineText = + UnownedStringSlice(remaining.begin(), remaining.begin() + endIndex); Int line; SLANG_RETURN_ON_FAIL(StringUtil::parseInt(lineText, line)); @@ -208,7 +210,10 @@ static bool _hasDriveLetter(const UnownedStringSlice& line) return line.getLength() > 2 && line[1] == ':' && _isDriveLetter(line[0]); } -static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStringSlice& line, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseNVRTCLine( + SliceAllocator& allocator, + const UnownedStringSlice& line, + ArtifactDiagnostic& outDiagnostic) { typedef ArtifactDiagnostic Diagnostic; typedef ArtifactDiagnostic::Severity Severity; @@ -218,7 +223,7 @@ static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStrin List split; if (_hasDriveLetter(line)) { - // The drive letter has :, which confuses things, so skip that and then fix up first entry + // The drive letter has :, which confuses things, so skip that and then fix up first entry UnownedStringSlice lineWithoutDrive(line.begin() + 2, line.end()); StringUtil::split(lineWithoutDrive, ':', split); split[0] = UnownedStringSlice(line.begin(), split[0].end()); @@ -235,8 +240,7 @@ static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStrin Severity severity = Severity::Unknown; - if (split1 == toSlice("error") || - split1 == toSlice("catastrophic error")) + if (split1 == toSlice("error") || split1 == toSlice("catastrophic error")) { severity = Severity::Error; } @@ -246,14 +250,14 @@ static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStrin } else { - // Fall back position to try and determine if this really is some kind of - // error/warning without succeeding when it's due to some other property - // of the output diagnostics. + // Fall back position to try and determine if this really is some kind of + // error/warning without succeeding when it's due to some other property + // of the output diagnostics. // // Anything ending with " warning:" or " error:" in effect. - - // We can expand to include character after as this is split1, as must be followed by at a minimum - // : (as the split has at least 3 parts). + + // We can expand to include character after as this is split1, as must be followed by at + // a minimum : (as the split has at least 3 parts). const UnownedStringSlice expandSplit1(split1.begin(), split1.end() + 1); if (expandSplit1.endsWith(toSlice(" error:"))) @@ -268,9 +272,9 @@ static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStrin if (severity != Severity::Unknown) { - // The text is everything following the : after the warning. + // The text is everything following the : after the warning. UnownedStringSlice text(split[2].begin(), split.getLast().end()); - + // Trim whitespace at start and end text = text.trim(); @@ -282,19 +286,18 @@ static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStrin return SLANG_OK; } - // TODO(JS): Note here if it's not possible to determine a line as being the main diagnostics - // we fall through to it potentially being a note. + // TODO(JS): Note here if it's not possible to determine a line as being the main + // diagnostics we fall through to it potentially being a note. + // + // That could mean a valid diagnostic (from NVRTCs point of view) is ignored/noted, because + // this code can't parse it. Ideally that situation would lead to an error such that we can + // detect and things will fail. // - // That could mean a valid diagnostic (from NVRTCs point of view) is ignored/noted, because this code - // can't parse it. Ideally that situation would lead to an error such that we can detect - // and things will fail. - // // So we might want to revisit this determination in the future. } // There isn't a diagnostic on this line - if (line.getLength() == 0 || - line.trim().getLength() == 0) + if (line.getLength() == 0 || line.trim().getLength() == 0) { return SLANG_E_NOT_FOUND; } @@ -306,14 +309,18 @@ static SlangResult _parseNVRTCLine(SliceAllocator& allocator, const UnownedStrin return SLANG_OK; } -/* An implementation of Path::Visitor that can be used for finding NVRTC shared library installations. */ +/* An implementation of Path::Visitor that can be used for finding NVRTC shared library + * installations. */ struct NVRTCPathVisitor : Path::Visitor { struct Candidate { typedef Candidate ThisType; - bool operator==(const ThisType& rhs) const { return path == rhs.path && version == rhs.version; } + bool operator==(const ThisType& rhs) const + { + return path == rhs.path && version == rhs.version; + } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } static Candidate make(const String& path, const SemanticVersion& version) @@ -340,10 +347,13 @@ struct NVRTCPathVisitor : Path::Visitor return -1; } - static bool _orderCandiate(const Candidate& a, const Candidate& b) { return a.version < b.version; } + static bool _orderCandiate(const Candidate& a, const Candidate& b) + { + return a.version < b.version; + } void sortCandidates() { m_candidates.sort(_orderCandiate); } - + #if SLANG_WINDOWS_FAMILY SlangResult getVersion(const UnownedStringSlice& filename, SemanticVersion& outVersion) { @@ -356,7 +366,9 @@ struct NVRTCPathVisitor : Path::Visitor endIndex = (endIndex < 0) ? filename.getLength() : endIndex; // If we have a version slice, split it - UnownedStringSlice versionSlice = UnownedStringSlice(filename.begin() + m_prefix.getLength(), filename.begin() + endIndex); + UnownedStringSlice versionSlice = UnownedStringSlice( + filename.begin() + m_prefix.getLength(), + filename.begin() + endIndex); if (versionSlice.getLength() <= 0) { @@ -382,7 +394,8 @@ struct NVRTCPathVisitor : Path::Visitor } UnownedStringSlice majorSlice = majorMinorSlice.head(majorMinorSlice.getLength() - 1); - UnownedStringSlice minorSlice = majorMinorSlice.subString(majorMinorSlice.getLength() - 1, 1); + UnownedStringSlice minorSlice = + majorMinorSlice.subString(majorMinorSlice.getLength() - 1, 1); Int major; Int minor; @@ -396,7 +409,8 @@ struct NVRTCPathVisitor : Path::Visitor #else // How the path is constructed depends on platform // https://docs.nvidia.com/cuda/nvrtc/index.html - // TODO(JS): Handle version number depending on the platform - it's different for Windows/OSX/Linux + // TODO(JS): Handle version number depending on the platform - it's different for + // Windows/OSX/Linux SlangResult getVersion(const UnownedStringSlice& filename, SemanticVersion& outVersion) { SLANG_UNUSED(filename); @@ -415,16 +429,18 @@ struct NVRTCPathVisitor : Path::Visitor if (m_postfix.getLength() && filename.getLength() >= m_postfix.getLength()) { // We test without case - really for windows - UnownedStringSlice filenamePostfix = filename.tail(filename.getLength() - m_postfix.getLength()); + UnownedStringSlice filenamePostfix = + filename.tail(filename.getLength() - m_postfix.getLength()); if (!filenamePostfix.caseInsensitiveEquals(m_postfix.getUnownedSlice())) { return; } } - + if (filename.getLength() >= m_prefix.getLength() && - filename.subString(0, m_prefix.getLength()).caseInsensitiveEquals(m_prefix.getUnownedSlice())) + filename.subString(0, m_prefix.getLength()) + .caseInsensitiveEquals(m_prefix.getUnownedSlice())) { SemanticVersion version; // If it produces an error, just use 0.0.0 @@ -433,8 +449,9 @@ struct NVRTCPathVisitor : Path::Visitor version = SemanticVersion(); } - // We may want to add multiple versions, if they are in different locations - as there may be multiple entries - // in the PATH, and only one works. We'll only know which works by loading + // We may want to add multiple versions, if they are in different locations - as + // there may be multiple entries in the PATH, and only one works. We'll only know + // which works by loading #if 0 // We already found this version, so let's not add it again @@ -445,10 +462,12 @@ struct NVRTCPathVisitor : Path::Visitor #endif // Strip to make a shared library name - UnownedStringSlice sharedLibraryName = filename.tail(m_prefix.getLength() - m_sharedLibraryStem.getLength()); + UnownedStringSlice sharedLibraryName = + filename.tail(m_prefix.getLength() - m_sharedLibraryStem.getLength()); sharedLibraryName = filename.head(filename.getLength() - m_postfix.getLength()); - auto candidate = Candidate::make(Path::combine(m_basePath, sharedLibraryName), version); + auto candidate = + Candidate::make(Path::combine(m_basePath, sharedLibraryName), version); // If we already have this candidate, then skip if (m_candidates.indexOf(candidate) >= 0) @@ -470,8 +489,8 @@ struct NVRTCPathVisitor : Path::Visitor bool hasCandidates() const { return m_candidates.getCount() > 0; } - NVRTCPathVisitor(const UnownedStringSlice& sharedLibraryStem) : - m_sharedLibraryStem(sharedLibraryStem) + NVRTCPathVisitor(const UnownedStringSlice& sharedLibraryStem) + : m_sharedLibraryStem(sharedLibraryStem) { // Work out the prefix and postfix of the shader StringBuilder buf; @@ -491,7 +510,7 @@ struct NVRTCPathVisitor : Path::Visitor List m_candidates; }; -template +template SLANG_FORCE_INLINE static void _unusedFunction(const T& func) { SLANG_UNUSED(func); @@ -508,7 +527,8 @@ static UnownedStringSlice _getNVRTCBaseName() #endif } -// Candidates are in m_candidates list. Will be ordered from the oldest to newest (in version number) +// Candidates are in m_candidates list. Will be ordered from the oldest to newest (in version +// number) static SlangResult _findNVRTC(NVRTCPathVisitor& visitor) { // First try the instance path (if supported on platform) @@ -524,7 +544,9 @@ static SlangResult _findNVRTC(NVRTCPathVisitor& visitor) if (!visitor.hasCandidates()) { StringBuilder buf; - if (!SLANG_SUCCEEDED(PlatformUtil::getEnvironmentVariable(UnownedStringSlice::fromLiteral("CUDA_PATH"), buf))) + if (!SLANG_SUCCEEDED(PlatformUtil::getEnvironmentVariable( + UnownedStringSlice::fromLiteral("CUDA_PATH"), + buf))) { // Look for candidates in the directory visitor.findInDirectory(Path::combine(buf, "bin")); @@ -537,7 +559,8 @@ static SlangResult _findNVRTC(NVRTCPathVisitor& visitor) List splitPath; StringBuilder buf; - if (SLANG_SUCCEEDED(PlatformUtil::getEnvironmentVariable(UnownedStringSlice::fromLiteral("PATH"), buf))) + if (SLANG_SUCCEEDED( + PlatformUtil::getEnvironmentVariable(UnownedStringSlice::fromLiteral("PATH"), buf))) { // Split so we get individual paths List paths; @@ -546,19 +569,22 @@ static SlangResult _findNVRTC(NVRTCPathVisitor& visitor) // We use a pool to make sure we only check each path once StringSlicePool pool(StringSlicePool::Style::Empty); - // We are going to search the paths in order + // We are going to search the paths in order for (const auto& path : paths) { - // PATH can have the same path multiple times. If we have already searched this path, we don't need to again + // PATH can have the same path multiple times. If we have already searched this + // path, we don't need to again if (!pool.has(path)) { pool.add(path); Path::split(path, splitPath); - // We could search every path, but here we restrict to paths that look like CUDA installations. - // It's a path that contains a CUDA directory and has bin - if (splitPath.indexOf("CUDA") >= 0 && splitPath[splitPath.getCount() - 1].caseInsensitiveEquals(UnownedStringSlice::fromLiteral("bin"))) + // We could search every path, but here we restrict to paths that look like CUDA + // installations. It's a path that contains a CUDA directory and has bin + if (splitPath.indexOf("CUDA") >= 0 && + splitPath[splitPath.getCount() - 1].caseInsensitiveEquals( + UnownedStringSlice::fromLiteral("bin"))) { // Okay lets search it visitor.findInDirectory(path); @@ -568,11 +594,11 @@ static SlangResult _findNVRTC(NVRTCPathVisitor& visitor) } } - // Put into version order with oldest first. + // Put into version order with oldest first. visitor.sortCandidates(); return SLANG_OK; -} +} static const UnownedStringSlice g_fp16HeaderName = UnownedStringSlice::fromLiteral("cuda_fp16.h"); @@ -591,7 +617,10 @@ SlangResult NVRTCDownstreamCompiler::_getIncludePath(String& outPath) return m_includePath.getLength() ? SLANG_OK : SLANG_E_NOT_FOUND; } -SlangResult _findFileInIncludePath(const String& path, const UnownedStringSlice& filename, String& outPath) +SlangResult _findFileInIncludePath( + const String& path, + const UnownedStringSlice& filename, + String& outPath) { if (File::exists(Path::combine(path, filename))) { @@ -624,8 +653,8 @@ SlangResult NVRTCDownstreamCompiler::_findIncludePath(String& outPath) { outPath = String(); - // Try looking up from a symbol. This will work as long as the nvrtc is loaded somehow from a dll/sharedlibrary - // And the header is included from there + // Try looking up from a symbol. This will work as long as the nvrtc is loaded somehow from a + // dll/sharedlibrary And the header is included from there { String libPath = SharedLibraryUtils::getSharedLibraryFileName((void*)m_nvrtcCreateProgram); if (libPath.getLength()) @@ -646,8 +675,7 @@ SlangResult NVRTCDownstreamCompiler::_findIncludePath(String& outPath) // This -2 split holds the version number. const auto pathSplitCount = pathSlices.getCount(); - if (pathSplitCount >= 3 && - pathSlices[pathSplitCount - 1] == toSlice("bin") && + if (pathSplitCount >= 3 && pathSlices[pathSplitCount - 1] == toSlice("bin") && pathSlices[pathSplitCount - 3] == toSlice("CUDA")) { // We want to make sure that one of these paths is CUDA... @@ -665,7 +693,9 @@ SlangResult NVRTCDownstreamCompiler::_findIncludePath(String& outPath) // Try CUDA_PATH environment variable { StringBuilder buf; - if (SLANG_SUCCEEDED(PlatformUtil::getEnvironmentVariable(UnownedStringSlice::fromLiteral("CUDA_PATH"), buf))) + if (SLANG_SUCCEEDED(PlatformUtil::getEnvironmentVariable( + UnownedStringSlice::fromLiteral("CUDA_PATH"), + buf))) { String includePath = Path::combine(buf, "include"); @@ -680,7 +710,9 @@ SlangResult NVRTCDownstreamCompiler::_findIncludePath(String& outPath) return SLANG_E_NOT_FOUND; } -SlangResult NVRTCDownstreamCompiler::_maybeAddHalfSupport(const DownstreamCompileOptions& options, CommandLine& ioCmdLine) +SlangResult NVRTCDownstreamCompiler::_maybeAddHalfSupport( + const DownstreamCompileOptions& options, + CommandLine& ioCmdLine) { if ((options.flags & DownstreamCompileOptions::Flag::EnableFloat16) == 0) { @@ -725,7 +757,9 @@ SlangResult NVRTCDownstreamCompiler::_maybeAddHalfSupport(const DownstreamCompil return SLANG_OK; } -SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inOptions, IArtifact** outArtifact) +SlangResult NVRTCDownstreamCompiler::compile( + const DownstreamCompileOptions& inOptions, + IArtifact** outArtifact) { if (!isVersionCompatible(inOptions)) { @@ -747,16 +781,16 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO switch (options.debugInfoType) { - case DebugInfoType::None: + case DebugInfoType::None: { break; } - default: + default: { cmdLine.addArg("--device-debug"); break; } - case DebugInfoType::Maximal: + case DebugInfoType::Maximal: { cmdLine.addArg("--device-debug"); cmdLine.addArg("--generate-line-info"); @@ -765,19 +799,19 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO } // Don't seem to have such a control, so ignore for now - //switch (options.optimizationLevel) + // switch (options.optimizationLevel) //{ // default: break; //} switch (options.floatingPointMode) { - case FloatingPointMode::Default: break; - case FloatingPointMode::Precise: + case FloatingPointMode::Default: break; + case FloatingPointMode::Precise: { break; } - case FloatingPointMode::Fast: + case FloatingPointMode::Fast: { cmdLine.addArg("--use_fast_math"); break; @@ -815,8 +849,9 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO cmdLine.addArg("-std=c++17"); // Disable all warnings - // This is arguably too much - but nvrtc does not appear to have a mechanism to switch off individual warnings. - // I tried the -Xcudafe mechanism but that does not appear to work for nvrtc + // This is arguably too much - but nvrtc does not appear to have a mechanism to switch off + // individual warnings. I tried the -Xcudafe mechanism but that does not appear to work for + // nvrtc cmdLine.addArg("-w"); } @@ -827,13 +862,13 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO SemanticVersion version(3); // Newer releases of NVRTC only support newer CUDA architectures. - if ( m_desc.version.m_major >= 12 ) + if (m_desc.version.m_major >= 12) { // NVRTC in CUDA 12 only supports `compute_50` and up // (with everything before `compute_52` being deprecated). version = SemanticVersion(5, 0); } - else if ( m_desc.version.m_major == 11 ) + else if (m_desc.version.m_major == 11) { // NVRTC in CUDA 11 only supports `compute_35` and up // (with everything before `compute_52` being deprecated). @@ -871,7 +906,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO // If compiling for OptiX, we need to add the appropriate search paths to the command line. // - if(options.pipelineType == PipelineType::RayTracing) + if (options.pipelineType == PipelineType::RayTracing) { // The device-side OptiX API is accessed through a constellation // of headers provided by the OptiX SDK, so we need to set an @@ -906,7 +941,8 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO // TODO: Confirm that the `LP64` definition here is actually needed. // headerIncludeNames.add("stddef.h"); - headers.add("#pragma once\n" "#define LP64\n"); + headers.add("#pragma once\n" + "#define LP64\n"); // Finally, we want the CUDA prelude to be able to react to whether // or not OptiX is required (most notably by `#include`ing the appropriate @@ -923,7 +959,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO { for (auto compilerSpecificArg : options.compilerSpecificArguments) { - const char*const arg = compilerSpecificArg; + const char* const arg = compilerSpecificArg; cmdLine.addArg(arg); } } @@ -939,7 +975,10 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO auto sourceContents = SliceUtil::toTerminatedCharSlice(storage, sourceBlob); nvrtcProgram program = nullptr; - nvrtcResult res = m_nvrtcCreateProgram(&program, sourceContents, String(sourcePath).getBuffer(), + nvrtcResult res = m_nvrtcCreateProgram( + &program, + sourceContents, + String(sourcePath).getBuffer(), (int)headers.getCount(), headers.getBuffer(), headerIncludeNames.getBuffer()); @@ -956,7 +995,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO dstOptions[i] = cmdLine.m_args[i].getBuffer(); } - res = m_nvrtcCompileProgram(program, int(dstOptions.getCount()), dstOptions.getBuffer()); + res = m_nvrtcCompileProgram(program, int(dstOptions.getCount()), dstOptions.getBuffer()); auto artifact = ArtifactUtil::createArtifactForCompileTarget(options.targetType); auto diagnostics = ArtifactDiagnostics::create(); @@ -1024,7 +1063,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO if (SLANG_SUCCEEDED(lineRes)) { // We only allow info diagnostics after a 'regular' diagnostic. - if (diagnostic.severity == ArtifactDiagnostic::Severity::Info && + if (diagnostic.severity == ArtifactDiagnostic::Severity::Info && diagnostics->getCount() == 0) { continue; @@ -1042,7 +1081,7 @@ SlangResult NVRTCDownstreamCompiler::compile(const DownstreamCompileOptions& inO // If it has a compilation error.. and there isn't already an error set // set as failed. - if (SLANG_SUCCEEDED(diagnostics->getResult()) && + if (SLANG_SUCCEEDED(diagnostics->getResult()) && diagnostics->hasOfAtLeastSeverity(ArtifactDiagnostic::Severity::Error)) { diagnostics->setResult(SLANG_FAIL); @@ -1072,7 +1111,10 @@ bool NVRTCDownstreamCompiler::canConvert(const ArtifactDesc& from, const Artifac return ArtifactDescUtil::isDisassembly(from, to) || ArtifactDescUtil::isDisassembly(to, from); } -SlangResult NVRTCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) +SlangResult NVRTCDownstreamCompiler::convert( + IArtifact* from, + const ArtifactDesc& to, + IArtifact** outArtifact) { if (!canConvert(from->getDesc(), to)) { @@ -1080,8 +1122,8 @@ SlangResult NVRTCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc } // PTX is 'binary like' and 'assembly like' so we allow conversion either way - // We do it by just getting as a blob and sharing that blob. - // A more sophisticated implementation could proxy to the original artifact, but this + // We do it by just getting as a blob and sharing that blob. + // A more sophisticated implementation could proxy to the original artifact, but this // is simpler, and probably fine in most scenarios. ComPtr blob; SLANG_RETURN_ON_FAIL(from->loadBlob(ArtifactKeep::Yes, blob.writeRef())); @@ -1093,11 +1135,13 @@ SlangResult NVRTCDownstreamCompiler::convert(IArtifact* from, const ArtifactDesc return SLANG_OK; } -static SlangResult _findAndLoadNVRTC(ISlangSharedLibraryLoader* loader, ComPtr& outLibrary) +static SlangResult _findAndLoadNVRTC( + ISlangSharedLibraryLoader* loader, + ComPtr& outLibrary) { #if SLANG_WINDOWS_FAMILY && SLANG_PTR_IS_64 - // We only need to search 64 bit versions on windows + // We only need to search 64 bit versions on windows NVRTCPathVisitor visitor(_getNVRTCBaseName()); SLANG_RETURN_ON_FAIL(_findNVRTC(visitor)); @@ -1105,7 +1149,8 @@ static SlangResult _findAndLoadNVRTC(ISlangSharedLibraryLoader* loader, ComPtr= 0; --i) { const auto& candidate = visitor.m_candidates[i]; - if (SLANG_SUCCEEDED(loader->loadSharedLibrary(candidate.path.getBuffer(), outLibrary.writeRef()))) + if (SLANG_SUCCEEDED( + loader->loadSharedLibrary(candidate.path.getBuffer(), outLibrary.writeRef()))) { return SLANG_OK; } @@ -1121,16 +1166,19 @@ static SlangResult _findAndLoadNVRTC(ISlangSharedLibraryLoader* loader, ComPtr library; @@ -1148,8 +1196,8 @@ static SlangResult _findAndLoadNVRTC(ISlangSharedLibraryLoader* loader, ComPtrloadSharedLibrary("nvrtc", library.writeRef()))) { // Try something more sophisticated to locate NVRTC @@ -1171,4 +1219,4 @@ static SlangResult _findAndLoadNVRTC(ISlangSharedLibraryLoader* loader, ComPtr includes, - const HashParams& hashParams, - const List values) - { - StringBuilder sb; - StringWriter writer(&sb, WriterFlags(0)); - WriterHelper w(&writer); +SlangResult writeHashFile( + String outCppPath, + String valueType, + const List includes, + const HashParams& hashParams, + const List values) +{ + StringBuilder sb; + StringWriter writer(&sb, WriterFlags(0)); + WriterHelper w(&writer); - w.print("// Hash function for %s\n", valueType.getBuffer()); - w.print("//\n"); - w.print("// This file was thoughtfully generated by a machine,\n"); - w.print("// don't even think about modifying it yourself!\n"); - w.print("//\n"); - w.print("\n"); - for (const auto& i : includes) - { - if (i.getLength()) - w.print("#include \"%s\"\n", i.getBuffer()); - } - w.print("\n"); - w.print("\n"); - w.print("namespace Slang\n"); - w.print("{\n"); - w.print("\n"); + w.print("// Hash function for %s\n", valueType.getBuffer()); + w.print("//\n"); + w.print("// This file was thoughtfully generated by a machine,\n"); + w.print("// don't even think about modifying it yourself!\n"); + w.print("//\n"); + w.print("\n"); + for (const auto& i : includes) + { + if (i.getLength()) + w.print("#include \"%s\"\n", i.getBuffer()); + } + w.print("\n"); + w.print("\n"); + w.print("namespace Slang\n"); + w.print("{\n"); + w.print("\n"); - w.put(perfectHashToEmbeddableCpp( - hashParams, - valueType.getUnownedSlice(), - (String("lookup") + valueType).getUnownedSlice(), - values - ).getBuffer()); + w.put(perfectHashToEmbeddableCpp( + hashParams, + valueType.getUnownedSlice(), + (String("lookup") + valueType).getUnownedSlice(), + values) + .getBuffer()); - w.print("}\n"); + w.print("}\n"); - return File::writeAllTextIfChanged(outCppPath, sb.getUnownedSlice()); - } + return File::writeAllTextIfChanged(outCppPath, sb.getUnownedSlice()); +} - SlangResult writePerfectHashLookupCppFile(String fileName, List opnames, String enumName, String enumerantPrefix, String enumHeaderFile, DiagnosticSink* sink) +SlangResult writePerfectHashLookupCppFile( + String fileName, + List opnames, + String enumName, + String enumerantPrefix, + String enumHeaderFile, + DiagnosticSink* sink) +{ + HashParams hashParams; + auto r = minimalPerfectHash(opnames, hashParams); + switch (r) { - HashParams hashParams; - auto r = minimalPerfectHash(opnames, hashParams); - switch (r) - { - case HashFindResult::UnavoidableHashCollision: + case HashFindResult::UnavoidableHashCollision: { sink->diagnoseRaw( Severity::Error, @@ -58,24 +65,24 @@ namespace Slang "collision for some input words\n"); return SLANG_FAIL; } - case HashFindResult::NonUniqueKeys: + case HashFindResult::NonUniqueKeys: { sink->diagnoseRaw(Severity::Error, "Input word list has duplicates\n"); return SLANG_FAIL; } - case HashFindResult::Success:; - } - - List values; - values.reserve(hashParams.destTable.getCount()); - for (const auto& v : hashParams.destTable) - values.add(enumerantPrefix + v); - return writeHashFile( - fileName, - enumName, - { "core/slang-common.h", "core/slang-string.h", enumHeaderFile }, - hashParams, - values); + case HashFindResult::Success:; } + List values; + values.reserve(hashParams.destTable.getCount()); + for (const auto& v : hashParams.destTable) + values.add(enumerantPrefix + v); + return writeHashFile( + fileName, + enumName, + {"core/slang-common.h", "core/slang-string.h", enumHeaderFile}, + hashParams, + values); } + +} // namespace Slang diff --git a/source/compiler-core/slang-perfect-hash-codegen.h b/source/compiler-core/slang-perfect-hash-codegen.h index 557f4dba5..d1ddd49b5 100644 --- a/source/compiler-core/slang-perfect-hash-codegen.h +++ b/source/compiler-core/slang-perfect-hash-codegen.h @@ -1,9 +1,15 @@ #pragma once -#include "slang-perfect-hash.h" #include "slang-diagnostic-sink.h" +#include "slang-perfect-hash.h" namespace Slang { - SlangResult writePerfectHashLookupCppFile(String fileName, List opnames, String enumName, String enumPrefix, String enumHeaderFile, DiagnosticSink* sink); +SlangResult writePerfectHashLookupCppFile( + String fileName, + List opnames, + String enumName, + String enumPrefix, + String enumHeaderFile, + DiagnosticSink* sink); } diff --git a/source/compiler-core/slang-perfect-hash.cpp b/source/compiler-core/slang-perfect-hash.cpp index a741f013c..a2dd88f98 100644 --- a/source/compiler-core/slang-perfect-hash.cpp +++ b/source/compiler-core/slang-perfect-hash.cpp @@ -23,7 +23,7 @@ HashFindResult minimalPerfectHash(const List& ss, HashParams& hashParams } SLANG_ASSERT(UIndex(ss.getCount()) < std::numeric_limits::max()); - const UInt32 nBuckets = UInt32(ss.getCount()); + const UInt32 nBuckets = UInt32(ss.getCount()); List> initialBuckets; initialBuckets.setCount(nBuckets); @@ -55,7 +55,8 @@ HashFindResult minimalPerfectHash(const List& ss, HashParams& hashParams { initialBuckets[hash(s)].add(s); } - initialBuckets.stableSort([](const List& a, const List& b) { return a.getCount() > b.getCount(); }); + initialBuckets.stableSort([](const List& a, const List& b) + { return a.getCount() > b.getCount(); }); // These are our outputs, the salts are calculated such that for all input // word, x, hash(x, salt[hash(x, 0)]) is unique @@ -138,12 +139,16 @@ String perfectHashToEmbeddableCpp( StringBuilder sb; StringWriter writer(&sb, WriterFlags(0)); WriterHelper w(&writer); - const auto line = [&](const char* l){ + const auto line = [&](const char* l) + { w.put(l); w.put("\n"); }; - w.print("bool %s(const UnownedStringSlice& str, %s& value)\n", String(funcName).getBuffer(), String(valueType).getBuffer()); + w.print( + "bool %s(const UnownedStringSlice& str, %s& value)\n", + String(funcName).getBuffer(), + String(valueType).getBuffer()); line("{"); w.print(" static const unsigned tableSalt[%d] = {\n", (int)hashParams.saltTable.getCount()); @@ -176,11 +181,7 @@ String perfectHashToEmbeddableCpp( { const auto& s = hashParams.destTable[i]; const auto& v = values[i]; - w.print( - " {\"%s\", %s},\n", - s.getBuffer(), - v.getBuffer() - ); + w.print(" {\"%s\", %s},\n", s.getBuffer(), v.getBuffer()); } line(" };"); line(""); @@ -211,4 +212,4 @@ String perfectHashToEmbeddableCpp( return sb.produceString(); } -} +} // namespace Slang diff --git a/source/compiler-core/slang-perfect-hash.h b/source/compiler-core/slang-perfect-hash.h index 1488c7a62..50553eee7 100644 --- a/source/compiler-core/slang-perfect-hash.h +++ b/source/compiler-core/slang-perfect-hash.h @@ -1,7 +1,7 @@ #pragma once -#include "../core/slang-string.h" #include "../core/slang-list.h" +#include "../core/slang-string.h" namespace Slang { @@ -12,7 +12,8 @@ struct HashParams List destTable; }; -enum class HashFindResult { +enum class HashFindResult +{ Success, NonUniqueKeys, UnavoidableHashCollision, @@ -27,4 +28,4 @@ String perfectHashToEmbeddableCpp( const UnownedStringSlice& funcName, const List& values); -} +} // namespace Slang diff --git a/source/compiler-core/slang-slice-allocator.cpp b/source/compiler-core/slang-slice-allocator.cpp index 49fd6a571..d24c05e9f 100644 --- a/source/compiler-core/slang-slice-allocator.cpp +++ b/source/compiler-core/slang-slice-allocator.cpp @@ -3,7 +3,8 @@ #include "../core/slang-blob.h" -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SliceUtil !!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -20,7 +21,7 @@ namespace Slang { return list; } -/* static */const char* SliceUtil::getTerminated(ISlangBlob* blob, TerminatedCharSlice& outSlice) +/* static */ const char* SliceUtil::getTerminated(ISlangBlob* blob, TerminatedCharSlice& outSlice) { const auto size = blob->getBufferSize(); if (size == 0) @@ -29,7 +30,7 @@ namespace Slang { return outSlice.begin(); } - // If there is a 0 at the end byte, we are zero terminated + // If there is a 0 at the end byte, we are zero terminated const char* chars = (const char*)blob->getBufferPointer(); if (chars[size - 1] == 0) { @@ -51,7 +52,9 @@ namespace Slang { return nullptr; } -/* static */TerminatedCharSlice SliceUtil::toTerminatedCharSlice(SliceAllocator& allocator, ISlangBlob* blob) +/* static */ TerminatedCharSlice SliceUtil::toTerminatedCharSlice( + SliceAllocator& allocator, + ISlangBlob* blob) { TerminatedCharSlice slice; if (SliceUtil::getTerminated(blob, slice)) @@ -59,25 +62,29 @@ namespace Slang { return slice; } const auto size = blob->getBufferSize(); - // We are out of options, we just have to allocate with zero termination which allocateString does - auto dst = allocator.getArena().allocateString((const char*)blob->getBufferPointer(), Count(size)); + // We are out of options, we just have to allocate with zero termination which allocateString + // does + auto dst = + allocator.getArena().allocateString((const char*)blob->getBufferPointer(), Count(size)); return TerminatedCharSlice(dst, Count(size)); } -/* static */TerminatedCharSlice SliceUtil::toTerminatedCharSlice(StringBuilder& storage, ISlangBlob* blob) +/* static */ TerminatedCharSlice SliceUtil::toTerminatedCharSlice( + StringBuilder& storage, + ISlangBlob* blob) { TerminatedCharSlice slice; if (SliceUtil::getTerminated(blob, slice)) { return slice; } - + const auto size = blob->getBufferSize(); auto chars = (const char*)blob->getBufferPointer(); storage.clear(); storage.append(UnownedStringSlice(chars, size)); - + return TerminatedCharSlice(storage.getBuffer(), Count(size)); } diff --git a/source/compiler-core/slang-slice-allocator.h b/source/compiler-core/slang-slice-allocator.h index 8d61fa211..504fbe1b7 100644 --- a/source/compiler-core/slang-slice-allocator.h +++ b/source/compiler-core/slang-slice-allocator.h @@ -2,12 +2,11 @@ #ifndef SLANG_SLICE_ALLOCATOR_H #define SLANG_SLICE_ALLOCATOR_H -// Has definition of CharSlice +// Has definition of CharSlice +#include "../core/slang-memory-arena.h" #include "slang-artifact.h" #include "slang-com-ptr.h" -#include "../core/slang-memory-arena.h" - namespace Slang { @@ -16,50 +15,64 @@ struct SliceAllocator; struct SliceUtil { - /// Convert into a list of strings + /// Convert into a list of strings static List toList(const Slice& in); - /// Gets a 0 terminated string from a blob. If not possible returns nullptr + /// Gets a 0 terminated string from a blob. If not possible returns nullptr static const char* getTerminated(ISlangBlob* blob, TerminatedCharSlice& outSlice); - /// NOTE! the slice is only guarenteed to stay in scope whilst the blob does + /// NOTE! the slice is only guarenteed to stay in scope whilst the blob does static TerminatedCharSlice toTerminatedCharSlice(SliceAllocator& allocator, ISlangBlob* blob); - /// + /// static TerminatedCharSlice toTerminatedCharSlice(StringBuilder& storage, ISlangBlob* blob); - /// The slice will only be in scope whilst the string is - static TerminatedCharSlice asTerminatedCharSlice(const String& in) { auto unowned = in.getUnownedSlice(); return TerminatedCharSlice(unowned.begin(), unowned.getLength()); } + /// The slice will only be in scope whilst the string is + static TerminatedCharSlice asTerminatedCharSlice(const String& in) + { + auto unowned = in.getUnownedSlice(); + return TerminatedCharSlice(unowned.begin(), unowned.getLength()); + } - /// Get string as a char slice - static CharSlice asCharSlice(const String& in) { auto unowned = in.getUnownedSlice(); return CharSlice(unowned.begin(), unowned.getLength()); } + /// Get string as a char slice + static CharSlice asCharSlice(const String& in) + { + auto unowned = in.getUnownedSlice(); + return CharSlice(unowned.begin(), unowned.getLength()); + } - template - static Slice asSlice(const List>& list) { return makeSlice((T* const*)list.getBuffer(), list.getCount()); } + template + static Slice asSlice(const List>& list) + { + return makeSlice((T* const*)list.getBuffer(), list.getCount()); + } - /// Get a list as a slice - template - static Slice asSlice(const List& list) { return Slice(list.getBuffer(), list.getCount()); } + /// Get a list as a slice + template + static Slice asSlice(const List& list) + { + return Slice(list.getBuffer(), list.getCount()); + } - template + template static List> toComPtrList(const Slice& in) { ISlangUnknown* check = (T*)nullptr; SLANG_UNUSED(check); List> list; list.setCount(in.count); - for (Index i = 0; i < in.count; ++i) list[i] = ComPtr(in[i]); + for (Index i = 0; i < in.count; ++i) + list[i] = ComPtr(in[i]); return list; } private: - /* - A reason to wrap in a struct rather than have as free functions is doing so will lead to compile time - errors with incorrect usage around temporaries. + A reason to wrap in a struct rather than have as free functions is doing so will lead to compile + time errors with incorrect usage around temporaries. */ /// We don't want to make a temporary list into a slice.. - template + template static Slice asSlice(const List&& list) = delete; // We don't want temporaries to be 'asSliced' so disable static TerminatedCharSlice asTerminatedCharSlice(const String&& in) = delete; @@ -78,7 +91,7 @@ SLANG_FORCE_INLINE CharSlice asCharSlice(const UnownedStringSlice& slice) SLANG_FORCE_INLINE String asString(const CharSlice& slice) { - return String(slice.begin(), slice.end()); + return String(slice.begin(), slice.end()); } struct SliceAllocator @@ -87,21 +100,24 @@ struct SliceAllocator TerminatedCharSlice allocate(const UnownedStringSlice& slice); TerminatedCharSlice allocate(const String& in) { return allocate(in.getUnownedSlice()); } TerminatedCharSlice allocate(const char* in); - TerminatedCharSlice allocate(const char* start, const char* end) { return allocate(UnownedStringSlice(start, end)); } + TerminatedCharSlice allocate(const char* start, const char* end) + { + return allocate(UnownedStringSlice(start, end)); + } Slice allocate(const List& in); - /// Get the backing arena + /// Get the backing arena MemoryArena& getArena() { return m_arena; } void deallocateAll() { m_arena.deallocateAll(); } - SliceAllocator(): - m_arena(2097152) + SliceAllocator() + : m_arena(2097152) { } + protected: - MemoryArena m_arena; }; diff --git a/source/compiler-core/slang-source-embed-util.cpp b/source/compiler-core/slang-source-embed-util.cpp index ec0c005cf..a4d3bf629 100644 --- a/source/compiler-core/slang-source-embed-util.cpp +++ b/source/compiler-core/slang-source-embed-util.cpp @@ -3,35 +3,35 @@ // Artifact #include "../compiler-core/slang-artifact-desc-util.h" #include "../compiler-core/slang-artifact-util.h" - -#include "../core/slang-string-util.h" -#include "../core/slang-char-util.h" - -#include "../core/slang-string-escape-util.h" - #include "../core/slang-blob.h" +#include "../core/slang-char-util.h" #include "../core/slang-io.h" +#include "../core/slang-string-escape-util.h" +#include "../core/slang-string-util.h" namespace Slang { -namespace { // anonymous +namespace +{ // anonymous typedef SourceEmbedUtil::Style Style; -} // anonymous - -static const NamesDescriptionValue kSourceEmbedStyleInfos[] = -{ - { ValueInt(Style::None), "none", "No source level embedding" }, - { ValueInt(Style::Default), "default", "The default embedding for the type to be embedded"}, - { ValueInt(Style::Text), "text", "Embed as text. May change line endings. If output isn't text will use 'default'. Size will *not* contain terminating 0." }, - { ValueInt(Style::BinaryText), "binary-text", "Embed as text assuming contents is binary. "}, - { ValueInt(Style::U8), "u8", "Embed as unsigned bytes."}, - { ValueInt(Style::U16), "u16", "Embed as uint16_t."}, - { ValueInt(Style::U32), "u32", "Embed as uint32_t."}, - { ValueInt(Style::U64), "u64", "Embed as uint64_t."}, +} // namespace + +static const NamesDescriptionValue kSourceEmbedStyleInfos[] = { + {ValueInt(Style::None), "none", "No source level embedding"}, + {ValueInt(Style::Default), "default", "The default embedding for the type to be embedded"}, + {ValueInt(Style::Text), + "text", + "Embed as text. May change line endings. If output isn't text will use 'default'. Size will " + "*not* contain terminating 0."}, + {ValueInt(Style::BinaryText), "binary-text", "Embed as text assuming contents is binary. "}, + {ValueInt(Style::U8), "u8", "Embed as unsigned bytes."}, + {ValueInt(Style::U16), "u16", "Embed as uint16_t."}, + {ValueInt(Style::U32), "u32", "Embed as uint32_t."}, + {ValueInt(Style::U64), "u64", "Embed as uint64_t."}, }; -/* static */ConstArrayView SourceEmbedUtil::getStyleInfos() +/* static */ ConstArrayView SourceEmbedUtil::getStyleInfos() { return makeConstArrayView(kSourceEmbedStyleInfos); } @@ -44,14 +44,11 @@ static const NamesDescriptionValue kSourceEmbedStyleInfos[] = static bool _isHeaderExtension(const UnownedStringSlice& in) { // Some "typical" header extensions - return in == toSlice("h") || - in == toSlice("hpp") || - in == toSlice("hxx") || - in == toSlice("h++") || - in == toSlice("hh"); + return in == toSlice("h") || in == toSlice("hpp") || in == toSlice("hxx") || + in == toSlice("h++") || in == toSlice("hh"); } -/* static */String SourceEmbedUtil::getPath(const String& path, const Options& options) +/* static */ String SourceEmbedUtil::getPath(const String& path, const Options& options) { if (!isSupported(options.language)) { @@ -76,7 +73,7 @@ static bool _isHeaderExtension(const UnownedStringSlice& in) return buf; } -/* static */SourceEmbedUtil::Style SourceEmbedUtil::getDefaultStyle(const ArtifactDesc& desc) +/* static */ SourceEmbedUtil::Style SourceEmbedUtil::getDefaultStyle(const ArtifactDesc& desc) { if (ArtifactDescUtil::isText(desc)) { @@ -97,7 +94,7 @@ static bool _isHeaderExtension(const UnownedStringSlice& in) return Style::U8; } -// True if we need to copy into a buffer. Necessary if there is an alignement +// True if we need to copy into a buffer. Necessary if there is an alignement // issue or if there is a partial entry static bool _needsCopy(const uint8_t* cur, Count bytesPerElement, Count bytesPerLine) { @@ -105,8 +102,13 @@ static bool _needsCopy(const uint8_t* cur, Count bytesPerElement, Count bytesPer } // NOTE! Assumes T is an unsigned type. Behavior will be incorrect if it is not. -template -static void _appendHex(const T* in, ArrayView elementWork, char* dst, size_t bytesForLine, StringBuilder& out) +template +static void _appendHex( + const T* in, + ArrayView elementWork, + char* dst, + size_t bytesForLine, + StringBuilder& out) { // Check that T is unsigned SLANG_COMPILE_TIME_ASSERT((T(~T(0))) > T(0)); @@ -138,10 +140,13 @@ static void _appendHex(const T* in, ArrayView elementWork, char* dst, size } } -static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayView data, StringBuilder& buf) +static SlangResult _append( + const SourceEmbedUtil::Options& options, + ConstArrayView data, + StringBuilder& buf) { const uint8_t* cur = data.begin(); - + const auto prefix = toSlice("0x"); const auto suffix = toSlice(", "); UnownedStringSlice literalSuffix; @@ -152,42 +157,42 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi switch (options.style) { - case Style::U8: + case Style::U8: { elementType = toSlice("unsigned char"); bytesPerElement = 1; break; } - case Style::U16: + case Style::U16: { elementType = toSlice("uint16_t"); bytesPerElement = 2; break; } - case Style::U32: + case Style::U32: { elementType = toSlice("uint32_t"); bytesPerElement = 4; break; } - case Style::U64: + case Style::U64: { elementType = toSlice("uint64_t"); bytesPerElement = 8; - // On testing on GCC/CLANG/Recent VS, there is no warning/error without suffix, so + // On testing on GCC/CLANG/Recent VS, there is no warning/error without suffix, so // will leave off for now. // literalSuffix = toSlice("ULL"); break; } - default: return SLANG_FAIL; + default: return SLANG_FAIL; } // Output the variable buf << "const " << elementType << " " << options.variableName << "[] = \n"; buf << "{\n"; - - // Work out the element work + + // Work out the element work char work[80]; Count elementSizeInChars; { @@ -227,7 +232,7 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi // We copy if we want alignment of if we hit a partial at the end if (_needsCopy(lineBytes, bytesPerElement, bytesForLine)) { - // Make sure the last element is zeroed, before copying + // Make sure the last element is zeroed, before copying // Needed if the last element is partial. alignedElements[Index(bytesForLine / sizeof(uint64_t))] = 0; @@ -242,10 +247,16 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi switch (bytesPerElement) { - case 1: _appendHex(lineBytes, workView, dstChars, bytesForLine, buf); break; - case 2: _appendHex((const uint16_t*)lineBytes, workView, dstChars, bytesForLine, buf); break; - case 4: _appendHex((const uint32_t*)lineBytes, workView, dstChars, bytesForLine, buf); break; - case 8: _appendHex((const uint64_t*)lineBytes, workView, dstChars, bytesForLine, buf); break; + case 1: _appendHex(lineBytes, workView, dstChars, bytesForLine, buf); break; + case 2: + _appendHex((const uint16_t*)lineBytes, workView, dstChars, bytesForLine, buf); + break; + case 4: + _appendHex((const uint32_t*)lineBytes, workView, dstChars, bytesForLine, buf); + break; + case 8: + _appendHex((const uint64_t*)lineBytes, workView, dstChars, bytesForLine, buf); + break; } buf << "\n"; @@ -256,7 +267,10 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi return SLANG_OK; } -/* static */SlangResult SourceEmbedUtil::createEmbedded(IArtifact* artifact, const Options& inOptions, ComPtr& outArtifact) +/* static */ SlangResult SourceEmbedUtil::createEmbedded( + IArtifact* artifact, + const Options& inOptions, + ComPtr& outArtifact) { if (!isSupported(inOptions.language)) { @@ -270,10 +284,9 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi Options options(inOptions); - // If the style is text, but the artifact *isn't* a text type, we'll + // If the style is text, but the artifact *isn't* a text type, we'll // use 'default' for the type - if (options.style == Style::Text && - !ArtifactDescUtil::isText(desc)) + if (options.style == Style::Text && !ArtifactDescUtil::isText(desc)) { options.style = Style::Default; } @@ -282,7 +295,7 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi { options.style = getDefaultStyle(desc); } - + // If there is no style there is nothing to do if (options.style == Style::None) { @@ -299,10 +312,10 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi ConstArrayView data((const uint8_t*)blob->getBufferPointer(), blob->getBufferSize()); size_t totalSizeInBytes = data.getCount(); - + switch (options.style) { - case Style::Text: + case Style::Text: { totalSizeInBytes = 0; @@ -321,8 +334,8 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi handler->appendEscaped(line, buf); - // Work out the total size, taking into account we may encode line endings and \0 differently - // The +1 is for \n + // Work out the total size, taking into account we may encode line endings and \0 + // differently The +1 is for \n totalSizeInBytes += line.getLength() + 1; buf << "\\n\"\n"; @@ -331,7 +344,7 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi buf << ";\n"; break; } - case Style::BinaryText: + case Style::BinaryText: { auto handler = StringEscapeUtil::getHandler(StringEscapeUtil::Style::Cpp); @@ -340,10 +353,10 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi // We could encode everything and then split // but if we do that we probably want to not split across an escaped character, // although that may be handled correctly. - + // The other way to this is incrementally, so that's what we will do here UnownedStringSlice text((const char*)data.begin(), data.getCount()); - + auto cur = text.begin(); auto end = text.end(); @@ -358,8 +371,7 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi { handler->appendEscaped(UnownedStringSlice(cur, 1), buf); cur++; - } - while (buf.getLength() - startOffset < options.lineLength - 1); + } while (buf.getLength() - startOffset < options.lineLength - 1); buf << "\"\n"; } @@ -367,24 +379,26 @@ static SlangResult _append(const SourceEmbedUtil::Options& options, ConstArrayVi buf << ";\n"; break; } - case Style::U8: - case Style::U16: - case Style::U32: - case Style::U64: + case Style::U8: + case Style::U16: + case Style::U32: + case Style::U64: { SLANG_RETURN_ON_FAIL(_append(options, data, buf)); break; } - default: + default: { return SLANG_E_NOT_IMPLEMENTED; } } - buf << "const size_t " << options.variableName << "_sizeInBytes = " << uint64_t(totalSizeInBytes) << ";\n\n"; + buf << "const size_t " << options.variableName + << "_sizeInBytes = " << uint64_t(totalSizeInBytes) << ";\n\n"; // Make into an artifact - ArtifactPayload payload = options.language == SLANG_SOURCE_LANGUAGE_C ? ArtifactPayload::C : ArtifactPayload::Cpp; + ArtifactPayload payload = + options.language == SLANG_SOURCE_LANGUAGE_C ? ArtifactPayload::C : ArtifactPayload::Cpp; auto dstDesc = ArtifactDesc::make(ArtifactKind::Source, payload); auto dstArtifact = ArtifactUtil::createArtifact(dstDesc); diff --git a/source/compiler-core/slang-source-embed-util.h b/source/compiler-core/slang-source-embed-util.h index 52115e4ef..9144bcb4c 100644 --- a/source/compiler-core/slang-source-embed-util.h +++ b/source/compiler-core/slang-source-embed-util.h @@ -2,13 +2,10 @@ #define SLANG_SOURCE_EMBED_UTIL_H #include "../core/slang-basic.h" - +#include "../core/slang-name-value.h" #include "slang-artifact.h" -#include "slang-diagnostic-sink.h" - #include "slang-com-ptr.h" - -#include "../core/slang-name-value.h" +#include "slang-diagnostic-sink.h" namespace Slang { @@ -18,42 +15,47 @@ struct SourceEmbedUtil { enum class Style : uint32_t { - None, ///< No embedding - Default, ///< Default embedding for the type - Text, ///< Embed as text. May change line endings. If output isn't text will use 'default'. Size will *not* contain terminating 0 - BinaryText, ///< Embed as text assuming contents is binary. - U8, ///< Embed as unsigned bytes - U16, ///< Embed as uint16_t - U32, ///< Embed as uint32_t - U64, ///< Embed as uint64_t + None, ///< No embedding + Default, ///< Default embedding for the type + Text, ///< Embed as text. May change line endings. If output isn't text will use 'default'. + ///< Size will *not* contain terminating 0 + BinaryText, ///< Embed as text assuming contents is binary. + U8, ///< Embed as unsigned bytes + U16, ///< Embed as uint16_t + U32, ///< Embed as uint32_t + U64, ///< Embed as uint64_t CountOf, }; struct Options { - Style style = Style::Default; ///< Style of embedding - Count lineLength = 120; ///< The line length, lines can be larger for some styles, but will aim to keep within range - SlangSourceLanguage language = SLANG_SOURCE_LANGUAGE_C; ///< The language to output for - String variableName; ///< The name to give the variable - String indent = " "; ///< Indenting + Style style = Style::Default; ///< Style of embedding + Count lineLength = 120; ///< The line length, lines can be larger for some styles, but will + ///< aim to keep within range + SlangSourceLanguage language = SLANG_SOURCE_LANGUAGE_C; ///< The language to output for + String variableName; ///< The name to give the variable + String indent = " "; ///< Indenting }; - /// Get the style infos + /// Get the style infos static ConstArrayView getStyleInfos(); - /// Given an artifact and - static SlangResult createEmbedded(IArtifact* artifact, const Options& options, ComPtr& outArtifact); + /// Given an artifact and + static SlangResult createEmbedded( + IArtifact* artifact, + const Options& options, + ComPtr& outArtifact); - /// Returns the default style for the desc + /// Returns the default style for the desc static Style getDefaultStyle(const ArtifactDesc& desc); - /// Returns true if supports the specified language for embedding + /// Returns true if supports the specified language for embedding static bool isSupported(SlangSourceLanguage lang); - /// Given the path return the output path. If no path is available return the empty string + /// Given the path return the output path. If no path is available return the empty string static String getPath(const String& path, const Options& options); }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/slang-source-loc.cpp b/source/compiler-core/slang-source-loc.cpp index 5f1f51a38..53eafbeaa 100644 --- a/source/compiler-core/slang-source-loc.cpp +++ b/source/compiler-core/slang-source-loc.cpp @@ -1,15 +1,16 @@ // slang-source-loc.cpp #include "slang-source-loc.h" -#include "../core/slang-string-util.h" -#include "../core/slang-string-escape-util.h" #include "../core/slang-char-encode.h" -#include "slang-artifact-representation-impl.h" +#include "../core/slang-string-escape-util.h" +#include "../core/slang-string-util.h" +#include "slang-artifact-desc-util.h" #include "slang-artifact-impl.h" +#include "slang-artifact-representation-impl.h" #include "slang-artifact-util.h" -#include "slang-artifact-desc-util.h" -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!! SourceView !!!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -17,13 +18,13 @@ const String PathInfo::getMostUniqueIdentity() const { switch (type) { - case Type::Normal: return uniqueIdentity; - case Type::FoundPath: - case Type::FromString: + case Type::Normal: return uniqueIdentity; + case Type::FoundPath: + case Type::FromString: { return foundPath; } - default: return ""; + default: return ""; } } @@ -31,9 +32,9 @@ String PathInfo::getName() const { switch (type) { - case Type::Normal: - case Type::FromString: - case Type::FoundPath: + case Type::Normal: + case Type::FromString: + case Type::FoundPath: { return foundPath; } @@ -51,24 +52,24 @@ bool PathInfo::operator==(const ThisType& rhs) const switch (type) { - case Type::TokenPaste: - case Type::TypeParse: - case Type::Unknown: - case Type::CommandLine: + case Type::TokenPaste: + case Type::TypeParse: + case Type::Unknown: + case Type::CommandLine: { return true; } - case Type::Normal: + case Type::Normal: { return foundPath == rhs.foundPath && uniqueIdentity == rhs.uniqueIdentity; } - case Type::FromString: - case Type::FoundPath: + case Type::FromString: + case Type::FoundPath: { // Only have a found path return foundPath == rhs.foundPath; } - default: break; + default: break; } return false; @@ -78,18 +79,21 @@ void PathInfo::appendDisplayName(StringBuilder& out) const { switch (type) { - case Type::TokenPaste: out << "[Token Paste]"; break; - case Type::TypeParse: out << "[Type Parse]"; break; - case Type::Unknown: out << "[Unknown]"; break; - case Type::CommandLine: out << "[Command Line]"; break; - case Type::Normal: - case Type::FromString: - case Type::FoundPath: + case Type::TokenPaste: out << "[Token Paste]"; break; + case Type::TypeParse: out << "[Type Parse]"; break; + case Type::Unknown: out << "[Unknown]"; break; + case Type::CommandLine: out << "[Command Line]"; break; + case Type::Normal: + case Type::FromString: + case Type::FoundPath: { - StringEscapeUtil::appendQuoted(StringEscapeUtil::getHandler(StringEscapeUtil::Style::Cpp), foundPath.getUnownedSlice(), out); + StringEscapeUtil::appendQuoted( + StringEscapeUtil::getHandler(StringEscapeUtil::Style::Cpp), + foundPath.getUnownedSlice(), + out); break; } - default: break; + default: break; } } @@ -104,10 +108,10 @@ int SourceView::findEntryIndex(SourceLoc sourceLoc) const const auto rawValue = sourceLoc.getRaw(); - Index hi = m_entries.getCount(); - // If there are no entries, or it is in front of the first entry, then there is no associated entry - if (hi == 0 || - m_entries[0].m_startLoc.getRaw() > sourceLoc.getRaw()) + Index hi = m_entries.getCount(); + // If there are no entries, or it is in front of the first entry, then there is no associated + // entry + if (hi == 0 || m_entries[0].m_startLoc.getRaw() > sourceLoc.getRaw()) { return -1; } @@ -133,29 +137,35 @@ int SourceView::findEntryIndex(SourceLoc sourceLoc) const return int(lo); } -void SourceView::addLineDirective(SourceLoc directiveLoc, StringSlicePool::Handle pathHandle, int line) +void SourceView::addLineDirective( + SourceLoc directiveLoc, + StringSlicePool::Handle pathHandle, + int line) { SLANG_ASSERT(pathHandle != StringSlicePool::Handle(0)); SLANG_ASSERT(m_range.contains(directiveLoc)); // Check that the directiveLoc values are always increasing - SLANG_ASSERT(m_entries.getCount() == 0 || (m_entries.getLast().m_startLoc.getRaw() < directiveLoc.getRaw())); + SLANG_ASSERT( + m_entries.getCount() == 0 || + (m_entries.getLast().m_startLoc.getRaw() < directiveLoc.getRaw())); // Calculate the offset const int offset = m_range.getOffset(directiveLoc); - + // Get the line index in the original file const int lineIndex = m_sourceFile->calcLineIndexFromOffset(offset); Entry entry; entry.m_startLoc = directiveLoc; entry.m_pathHandle = pathHandle; - + // We also need to make sure that any lookups for line numbers will // get corrected based on this files location. - // We assume the line number coming from the directive is a line number, NOT an index, so the correction needs + 1 - // There is an additional + 1 because we want the NEXT line - ie the line after the #line directive, to the specified value - // Taking both into account means +2 is correct 'fix' + // We assume the line number coming from the directive is a line number, NOT an index, so the + // correction needs + 1 There is an additional + 1 because we want the NEXT line - ie the line + // after the #line directive, to the specified value Taking both into account means +2 is + // correct 'fix' entry.m_lineAdjust = line - (lineIndex + 2); m_entries.add(entry); @@ -163,7 +173,8 @@ void SourceView::addLineDirective(SourceLoc directiveLoc, StringSlicePool::Handl void SourceView::addLineDirective(SourceLoc directiveLoc, const String& path, int line) { - StringSlicePool::Handle pathHandle = getSourceManager()->getStringSlicePool().add(path.getUnownedSlice()); + StringSlicePool::Handle pathHandle = + getSourceManager()->getStringSlicePool().add(path.getUnownedSlice()); return addLineDirective(directiveLoc, pathHandle, line); } @@ -171,9 +182,12 @@ void SourceView::addDefaultLineDirective(SourceLoc directiveLoc) { SLANG_ASSERT(m_range.contains(directiveLoc)); // Check that the directiveLoc values are always increasing - SLANG_ASSERT(m_entries.getCount() == 0 || (m_entries.getLast().m_startLoc.getRaw() < directiveLoc.getRaw())); + SLANG_ASSERT( + m_entries.getCount() == 0 || + (m_entries.getLast().m_startLoc.getRaw() < directiveLoc.getRaw())); - // Well if there are no entries, or the last one puts it in default case, then we don't need to add anything + // Well if there are no entries, or the last one puts it in default case, then we don't need to + // add anything if (m_entries.getCount() == 0 || (m_entries.getCount() && m_entries.getLast().isDefault())) { return; @@ -181,8 +195,9 @@ void SourceView::addDefaultLineDirective(SourceLoc directiveLoc) Entry entry; entry.m_startLoc = directiveLoc; - entry.m_lineAdjust = 0; // No line adjustment... we are going back to default - entry.m_pathHandle = StringSlicePool::Handle(0); // Mark that there is no path, and that this is a 'default' + entry.m_lineAdjust = 0; // No line adjustment... we are going back to default + entry.m_pathHandle = + StringSlicePool::Handle(0); // Mark that there is no path, and that this is a 'default' SLANG_ASSERT(entry.isDefault()); @@ -204,16 +219,20 @@ static bool _canFollowSourceMap(SourceFile* sourceFile, SourceLocType type) } // If it's obfuscated we can't follow if we are emitting - if (sourceFile->getSourceMapKind() == SourceMapKind::Obfuscated && - type == SourceLocType::Emit) + if (sourceFile->getSourceMapKind() == SourceMapKind::Obfuscated && type == SourceLocType::Emit) { return false; } - return _isNominalLike(type); + return _isNominalLike(type); } -static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, SourceView* sourceView, SourceLoc loc, SourceLocType type, HandleSourceLoc& outLoc) +static SlangResult _findLocWithSourceMap( + SourceManager* lookupSourceManager, + SourceView* sourceView, + SourceLoc loc, + SourceLocType type, + HandleSourceLoc& outLoc) { auto sourceFile = sourceView->getSourceFile(); @@ -229,9 +248,9 @@ static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, Sou Index entryIndex = -1; // Do the initial lookup using the loc - { + { const auto offset = sourceView->getRange().getOffset(loc); - + const auto lineIndex = sourceFile->calcLineIndexFromOffset(offset); const auto colIndex = sourceFile->calcColumnIndex(lineIndex, offset); @@ -239,7 +258,7 @@ static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, Sou auto sourceMap = sourceFile->getSourceMap(); SLANG_ASSERT(sourceMap); - entryIndex = sourceMap->get().findEntry(lineIndex, colIndex); + entryIndex = sourceMap->get().findEntry(lineIndex, colIndex); } if (entryIndex < 0) @@ -247,8 +266,8 @@ static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, Sou return SLANG_FAIL; } - // Keep searching through source maps - do + // Keep searching through source maps + do { auto sourceMap = sourceFile->getSourceMap()->getPtr(); @@ -259,7 +278,8 @@ static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, Sou // If we have a source name, see if it already exists in source manager if (sourceFileName.getLength()) { - if (auto foundSourceFile = lookupSourceManager->findSourceFileByPathRecursively(sourceFileName)) + if (auto foundSourceFile = + lookupSourceManager->findSourceFileByPathRecursively(sourceFileName)) { // We only follow if the source file hasn't already been visisted if (sourceFiles.indexOf(foundSourceFile) < 0) @@ -267,12 +287,14 @@ static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, Sou // Add so we don't reprocess sourceFiles.add(foundSourceFile); - // If it has a source map, we try and look up the current location in it's source map + // If it has a source map, we try and look up the current location in it's + // source map if (_canFollowSourceMap(foundSourceFile, type)) { auto foundSourceMap = foundSourceFile->getSourceMap(); - const auto foundEntryIndex = foundSourceMap->get().findEntry(entry.sourceLine, entry.sourceColumn); + const auto foundEntryIndex = + foundSourceMap->get().findEntry(entry.sourceLine, entry.sourceColumn); // If we found the entry repeat the lookup if (foundEntryIndex >= 0) @@ -304,7 +326,10 @@ static SlangResult _findLocWithSourceMap(SourceManager* lookupSourceManager, Sou } -SlangResult SourceView::_findSourceMapLoc(SourceLoc loc, SourceLocType type, HandleSourceLoc& outLoc) +SlangResult SourceView::_findSourceMapLoc( + SourceLoc loc, + SourceLocType type, + HandleSourceLoc& outLoc) { // We only do source map lookups with nominal if (!_isNominalLike(type)) @@ -312,9 +337,9 @@ SlangResult SourceView::_findSourceMapLoc(SourceLoc loc, SourceLocType type, Han return SLANG_E_NOT_FOUND; } - // TODO(JS): - // Ideally we'd do the lookup on the "current" source manager rather than the source manager on this - // view, which may be a parent to the current one. + // TODO(JS): + // Ideally we'd do the lookup on the "current" source manager rather than the source manager on + // this view, which may be a parent to the current one. auto lookupSourceManager = m_sourceFile->getSourceManager(); SLANG_RETURN_ON_FAIL(_findLocWithSourceMap(lookupSourceManager, this, loc, type, outLoc)); @@ -324,31 +349,32 @@ SlangResult SourceView::_findSourceMapLoc(SourceLoc loc, SourceLocType type, Han HandleSourceLoc SourceView::getHandleLoc(SourceLoc loc, SourceLocType type) { - { HandleSourceLoc handleLoc; + { + HandleSourceLoc handleLoc; if (SLANG_SUCCEEDED(_findSourceMapLoc(loc, type, handleLoc))) { return handleLoc; } } - // Get the offset in bytes for this loc + // Get the offset in bytes for this loc const int offset = m_range.getOffset(loc); // We need the line index from the original source file const int lineIndex = m_sourceFile->calcLineIndexFromOffset(offset); - // TODO: + // TODO: // - Tab characters, which should really adjust how we report // columns (although how are we supposed to know the setting // that an IDE expects us to use when reporting locations?) - // + // // For now we just count tabs as single chars const int columnIndex = m_sourceFile->calcColumnIndex(lineIndex, offset); HandleSourceLoc handleLoc; handleLoc.column = columnIndex + 1; handleLoc.line = lineIndex + 1; - + // Only bother looking up the entry information if we want a 'Norminal'-like lookup if (_isNominalLike(type)) { @@ -411,7 +437,7 @@ PathInfo SourceView::getPathInfo(SourceLoc loc, SourceLocType type) return getViewPathInfo(); } - { + { HandleSourceLoc handleLoc; if (SLANG_SUCCEEDED(_findSourceMapLoc(loc, type, handleLoc))) { @@ -420,7 +446,8 @@ PathInfo SourceView::getPathInfo(SourceLoc loc, SourceLocType type) } const int entryIndex = findEntryIndex(loc); - return _getPathInfoFromHandle((entryIndex >= 0) ? m_entries[entryIndex].m_pathHandle : StringSlicePool::Handle(0)); + return _getPathInfoFromHandle( + (entryIndex >= 0) ? m_entries[entryIndex].m_pathHandle : StringSlicePool::Handle(0)); } /* !!!!!!!!!!!!!!!!!!!!!!! SourceFile !!!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -464,13 +491,13 @@ SourceFile::OffsetRange SourceFile::getOffsetRangeAtLineIndex(Index lineIndex) const uint32_t offsetEnd = uint32_t(getContentSize()); const uint32_t offsetStart = (lineIndex >= count) ? offsetEnd : offsets[lineIndex]; // The line is the span from start, to the end of the content - return OffsetRange{ offsetStart, offsetEnd }; + return OffsetRange{offsetStart, offsetEnd}; } else { const uint32_t offsetStart = offsets[lineIndex]; const uint32_t offsetEnd = offsets[lineIndex + 1]; - return OffsetRange { offsetStart, offsetEnd }; + return OffsetRange{offsetStart, offsetEnd}; } } @@ -483,7 +510,7 @@ UnownedStringSlice SourceFile::getLineAtIndex(Index lineIndex) const UnownedStringSlice content = getContent(); SLANG_ASSERT(range.end <= uint32_t(content.getLength())); - const char*const text = content.begin(); + const char* const text = content.begin(); return UnownedStringSlice(text + range.start, text + range.end); } @@ -517,7 +544,7 @@ int SourceFile::calcLineIndexFromOffset(int offset) while (lo + 1 < hi) { - const Index mid = (hi + lo) >> 1; + const Index mid = (hi + lo) >> 1; const uint32_t midOffset = lineBreakOffsets[mid]; if (midOffset <= uint32_t(offset)) { @@ -535,14 +562,15 @@ int SourceFile::calcLineIndexFromOffset(int offset) int SourceFile::calcColumnOffset(int lineIndex, int offset) { const auto& lineBreakOffsets = getLineBreakOffsets(); - return offset - lineBreakOffsets[lineIndex]; + return offset - lineBreakOffsets[lineIndex]; } int SourceFile::calcColumnIndex(int lineIndex, int offset, int tabSize) { const int colOffset = calcColumnOffset(lineIndex, offset); - // If we don't have the content of the file, the best we can do is to assume there is a char per column + // If we don't have the content of the file, the best we can do is to assume there is a char per + // column if (!hasContent()) { return colOffset; @@ -553,7 +581,7 @@ int SourceFile::calcColumnIndex(int lineIndex, int offset, int tabSize) const auto head = line.head(colOffset); auto colCount = UTF8Util::calcCodePointCount(head); - + if (tabSize >= 0) { Count tabCount = 0; @@ -581,10 +609,7 @@ void SourceFile::setContents(ISlangBlob* blob) // Query the encoding type and discard the Unicode Byte-Order-Marker before decoding size_t offset; - auto type = CharEncoding::determineEncoding( - rawContentBegin, - rawContentSize, - offset); + auto type = CharEncoding::determineEncoding(rawContentBegin, rawContentSize, offset); SLANG_ASSERT(rawContentSize >= offset); List decodedBuffer; @@ -608,16 +633,12 @@ void SourceFile::setContents(const String& content) setContents(contentBlob); } -SourceFile::SourceFile(SourceManager* sourceManager, const PathInfo& pathInfo, size_t contentSize) : - m_sourceManager(sourceManager), - m_pathInfo(pathInfo), - m_contentSize(contentSize) +SourceFile::SourceFile(SourceManager* sourceManager, const PathInfo& pathInfo, size_t contentSize) + : m_sourceManager(sourceManager), m_pathInfo(pathInfo), m_contentSize(contentSize) { } -SourceFile::~SourceFile() -{ -} +SourceFile::~SourceFile() {} SHA1::Digest SourceFile::getDigest() { @@ -638,7 +659,10 @@ String SourceFile::calcVerbosePath() const { String displayPath; ComPtr displayPathBlob; - if (SLANG_SUCCEEDED(fileSystemExt->getPath(PathKind::Display, m_pathInfo.foundPath.getBuffer(), displayPathBlob.writeRef()))) + if (SLANG_SUCCEEDED(fileSystemExt->getPath( + PathKind::Display, + m_pathInfo.foundPath.getBuffer(), + displayPathBlob.writeRef()))) { displayPath = StringUtil::getString(displayPathBlob); } @@ -653,9 +677,7 @@ String SourceFile::calcVerbosePath() const /* !!!!!!!!!!!!!!!!!!!!!!!!! SourceManager !!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -void SourceManager::initialize( - SourceManager* p, - ISlangFileSystemExt* fileSystemExt) +void SourceManager::initialize(SourceManager* p, ISlangFileSystemExt* fileSystemExt) { m_fileSystemExt = fileSystemExt; @@ -730,8 +752,8 @@ SourceRange SourceManager::allocateSourceRange(UInt size) // TODO: consider using atomics here - SourceLoc beginLoc = m_nextLoc; - SourceLoc endLoc = beginLoc + size; + SourceLoc beginLoc = m_nextLoc; + SourceLoc endLoc = beginLoc + size; // We need to be able to represent the location that is *at* the end of // the input source, so the next available location for a new file @@ -749,7 +771,9 @@ SourceFile* SourceManager::createSourceFileWithSize(const PathInfo& pathInfo, si return sourceFile; } -SourceFile* SourceManager::createSourceFileWithString(const PathInfo& pathInfo, const String& contents) +SourceFile* SourceManager::createSourceFileWithString( + const PathInfo& pathInfo, + const String& contents) { SourceFile* sourceFile = new SourceFile(this, pathInfo, contents.getLength()); m_sourceFiles.add(sourceFile); @@ -765,13 +789,16 @@ SourceFile* SourceManager::createSourceFileWithBlob(const PathInfo& pathInfo, IS return sourceFile; } -SourceView* SourceManager::createSourceView(SourceFile* sourceFile, const PathInfo* pathInfo, SourceLoc initiatingSourceLoc) +SourceView* SourceManager::createSourceView( + SourceFile* sourceFile, + const PathInfo* pathInfo, + SourceLoc initiatingSourceLoc) { SourceRange range = allocateSourceRange(sourceFile->getContentSize()); SourceView* sourceView = nullptr; - if (pathInfo && - (pathInfo->foundPath.getLength() && sourceFile->getPathInfo().foundPath != pathInfo->foundPath)) + if (pathInfo && (pathInfo->foundPath.getLength() && + sourceFile->getPathInfo().foundPath != pathInfo->foundPath)) { sourceView = new SourceView(sourceFile, range, &pathInfo->foundPath, initiatingSourceLoc); } @@ -844,7 +871,7 @@ SourceView* SourceManager::findSourceViewRecursively(SourceLoc loc) const { // Start with this manager const SourceManager* manager = this; - do + do { SourceView* sourceView = manager->findSourceView(loc); // If we found a hit we are done @@ -854,8 +881,7 @@ SourceView* SourceManager::findSourceViewRecursively(SourceLoc loc) const } // Try the parent manager = manager->m_parent; - } - while (manager); + } while (manager); // Didn't find it return nullptr; } @@ -881,7 +907,7 @@ SourceFile* SourceManager::findSourceFileByPathRecursively(const String& name) c SourceFile* SourceManager::findSourceFileByPath(const String& name) const { - for(auto sourceFile : m_sourceFiles) + for (auto sourceFile : m_sourceFiles) { if (sourceFile->getPathInfo().foundPath == name) { @@ -893,14 +919,14 @@ SourceFile* SourceManager::findSourceFileByPath(const String& name) const SourceFile* SourceManager::findSourceFile(const String& uniqueIdentity) const { - SourceFile*const* filePtr = m_sourceFileMap.tryGetValue(uniqueIdentity); + SourceFile* const* filePtr = m_sourceFileMap.tryGetValue(uniqueIdentity); return (filePtr) ? *filePtr : nullptr; } SourceFile* SourceManager::findSourceFileRecursively(const String& uniqueIdentity) const { const SourceManager* manager = this; - do + do { SourceFile* sourceFile = manager->findSourceFile(uniqueIdentity); if (sourceFile) diff --git a/source/compiler-core/slang-source-loc.h b/source/compiler-core/slang-source-loc.h index bf0be47f6..c46c9063a 100644 --- a/source/compiler-core/slang-source-loc.h +++ b/source/compiler-core/slang-source-loc.h @@ -3,91 +3,126 @@ #define SLANG_SOURCE_LOC_H_INCLUDED #include "../core/slang-basic.h" -#include "../core/slang-memory-arena.h" -#include "../core/slang-string-slice-pool.h" #include "../core/slang-castable.h" #include "../core/slang-crypto.h" - -#include "slang-source-map.h" - +#include "../core/slang-memory-arena.h" +#include "../core/slang-string-slice-pool.h" #include "slang-com-ptr.h" +#include "slang-source-map.h" #include "slang.h" -namespace Slang { - -/** Overview: - -There needs to be a mechanism where we can easily and quickly track a specific locations in any source file used during a compilation. -This is important because that original location is meaningful to the user as it relates to their original source. Thus SourceLoc are -used so we can display meaningful and accurate errors/warnings as well as being able to always map generated code locations back to their origins. - -A 'SourceLoc' along with associated structures (SourceView, SourceFile, SourceMangager) this can pinpoint the location down to the byte across the -compilation. This could be achieved by storing for every token and instruction the file, line and column number came from. The SourceLoc is used in -lots of places - every AST node, every Token from the lexer, every IRInst - so we really want to make it small. So for this reason we actually -encode SourceLoc as a single integer and then use the associated structures when needed to determine what the location actually refers to - -the source file, line and column number, or in effect the byte in the original file. - -Unfortunately there is extra complications. When a source is parsed it's interpretation (in terms of how a piece of source maps to an 'original' file etc) -can be overridden - for example by using #line directives. Moreover a single source file can be parsed multiple times. When it's parsed multiple times the -interpretation of the mapping (#line directives for example) can change. This is the purpose of the SourceView - it holds the interpretation of a source file -for a specific Lex/Parse. - -Another complication is that not all 'source' comes from SourceFiles, a macro expansion, may generate new 'source' we need to handle this, but also be able -to have a SourceLoc map to the expansion unambiguously. This is handled by creating a SourceFile and SourceView that holds only the macro generated -specific information. +namespace Slang +{ -SourceFile - Is the immutable text contents of a file (or perhaps some generated source - say from doing a macro substitution) -SourceView - Tracks a single parse of a SourceFile. Each SourceView defines a range of source locations used. If a SourceFile is parsed twice, two -SourceViews are created, with unique SourceRanges. This is so that it is possible to tell which specific parse a SourceLoc is from - and so know the right -interpretation for that lex/parse. +/** Overview: + +There needs to be a mechanism where we can easily and quickly track a specific locations in any +source file used during a compilation. This is important because that original location is +meaningful to the user as it relates to their original source. Thus SourceLoc are used so we can +display meaningful and accurate errors/warnings as well as being able to always map generated code +locations back to their origins. + +A 'SourceLoc' along with associated structures (SourceView, SourceFile, SourceMangager) this can +pinpoint the location down to the byte across the compilation. This could be achieved by storing for +every token and instruction the file, line and column number came from. The SourceLoc is used in +lots of places - every AST node, every Token from the lexer, every IRInst - so we really want to +make it small. So for this reason we actually encode SourceLoc as a single integer and then use the +associated structures when needed to determine what the location actually refers to - the source +file, line and column number, or in effect the byte in the original file. + +Unfortunately there is extra complications. When a source is parsed it's interpretation (in terms of +how a piece of source maps to an 'original' file etc) can be overridden - for example by using #line +directives. Moreover a single source file can be parsed multiple times. When it's parsed multiple +times the interpretation of the mapping (#line directives for example) can change. This is the +purpose of the SourceView - it holds the interpretation of a source file for a specific Lex/Parse. + +Another complication is that not all 'source' comes from SourceFiles, a macro expansion, may +generate new 'source' we need to handle this, but also be able to have a SourceLoc map to the +expansion unambiguously. This is handled by creating a SourceFile and SourceView that holds only the +macro generated specific information. + +SourceFile - Is the immutable text contents of a file (or perhaps some generated source - say from +doing a macro substitution) SourceView - Tracks a single parse of a SourceFile. Each SourceView +defines a range of source locations used. If a SourceFile is parsed twice, two SourceViews are +created, with unique SourceRanges. This is so that it is possible to tell which specific parse a +SourceLoc is from - and so know the right interpretation for that lex/parse. */ struct PathInfo { typedef PathInfo ThisType; - /// To be more rigorous about where a path comes from, the type identifies what a paths origin is + /// To be more rigorous about where a path comes from, the type identifies what a paths origin + /// is enum class Type : uint8_t { - Unknown, ///< The path is not known - Normal, ///< Normal has both path and uniqueIdentity - FoundPath, ///< Just has a found path (uniqueIdentity is unknown, or even 'unknowable') - FromString, ///< Created from a string (so found path might not be defined and should not be taken as to map to a loaded file) - TokenPaste, ///< No paths, just created to do a macro expansion - TypeParse, ///< No path, just created to do a type parse - CommandLine, ///< A macro constructed from the command line + Unknown, ///< The path is not known + Normal, ///< Normal has both path and uniqueIdentity + FoundPath, ///< Just has a found path (uniqueIdentity is unknown, or even 'unknowable') + FromString, ///< Created from a string (so found path might not be defined and should not be + ///< taken as to map to a loaded file) + TokenPaste, ///< No paths, just created to do a macro expansion + TypeParse, ///< No path, just created to do a type parse + CommandLine, ///< A macro constructed from the command line }; - /// True if has a canonical path - SLANG_FORCE_INLINE bool hasUniqueIdentity() const { return type == Type::Normal && uniqueIdentity.getLength() > 0; } - /// True if has a regular found path - SLANG_FORCE_INLINE bool hasFoundPath() const { return (type == Type::Normal || type == Type::FoundPath || type == Type::FromString) && foundPath.getLength() > 0; } - /// True if has a found path that has originated from a file (as opposed to string or some other origin) - SLANG_FORCE_INLINE bool hasFileFoundPath() const { return (type == Type::Normal || type == Type::FoundPath) && foundPath.getLength() > 0; } - /// Get the 'name'/path of the item. Will return an empty string if not applicable or not set. + /// True if has a canonical path + SLANG_FORCE_INLINE bool hasUniqueIdentity() const + { + return type == Type::Normal && uniqueIdentity.getLength() > 0; + } + /// True if has a regular found path + SLANG_FORCE_INLINE bool hasFoundPath() const + { + return (type == Type::Normal || type == Type::FoundPath || type == Type::FromString) && + foundPath.getLength() > 0; + } + /// True if has a found path that has originated from a file (as opposed to string or some other + /// origin) + SLANG_FORCE_INLINE bool hasFileFoundPath() const + { + return (type == Type::Normal || type == Type::FoundPath) && foundPath.getLength() > 0; + } + /// Get the 'name'/path of the item. Will return an empty string if not applicable or not set. String getName() const; bool operator==(const ThisType& rhs) const; bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - /// Returns the 'most unique' identity for the path. If has a 'uniqueIdentity' returns that, else the foundPath, else "". + /// Returns the 'most unique' identity for the path. If has a 'uniqueIdentity' returns that, + /// else the foundPath, else "". const String getMostUniqueIdentity() const; - /// Append to out, how to display the path + /// Append to out, how to display the path void appendDisplayName(StringBuilder& out) const; - // So simplify construction. In normal usage it's safer to use make methods over constructing directly. - static PathInfo makeUnknown() { return PathInfo { Type::Unknown, String(), String() }; } - static PathInfo makeTokenPaste() { return PathInfo{ Type::TokenPaste, "token paste", String()}; } - static PathInfo makeNormal(const String& foundPathIn, const String& uniqueIdentity) { SLANG_ASSERT(uniqueIdentity.getLength() > 0 && foundPathIn.getLength() > 0); return PathInfo { Type::Normal, foundPathIn, uniqueIdentity }; } - static PathInfo makePath(const String& pathIn) { SLANG_ASSERT(pathIn.getLength() > 0); return PathInfo { Type::FoundPath, pathIn, String()}; } - static PathInfo makeTypeParse() { return PathInfo { Type::TypeParse, "type string", String() }; } - static PathInfo makeCommandLine() { return PathInfo { Type::CommandLine, "command line", String() }; } - static PathInfo makeFromString(const String& userPath) { return PathInfo{ Type::FromString, userPath, String() }; } - - Type type; ///< The type of path - String foundPath; ///< The path where the file was found (might contain relative elements) - String uniqueIdentity; ///< The unique identity of the file on the path found + // So simplify construction. In normal usage it's safer to use make methods over constructing + // directly. + static PathInfo makeUnknown() { return PathInfo{Type::Unknown, String(), String()}; } + static PathInfo makeTokenPaste() { return PathInfo{Type::TokenPaste, "token paste", String()}; } + static PathInfo makeNormal(const String& foundPathIn, const String& uniqueIdentity) + { + SLANG_ASSERT(uniqueIdentity.getLength() > 0 && foundPathIn.getLength() > 0); + return PathInfo{Type::Normal, foundPathIn, uniqueIdentity}; + } + static PathInfo makePath(const String& pathIn) + { + SLANG_ASSERT(pathIn.getLength() > 0); + return PathInfo{Type::FoundPath, pathIn, String()}; + } + static PathInfo makeTypeParse() { return PathInfo{Type::TypeParse, "type string", String()}; } + static PathInfo makeCommandLine() + { + return PathInfo{Type::CommandLine, "command line", String()}; + } + static PathInfo makeFromString(const String& userPath) + { + return PathInfo{Type::FromString, userPath, String()}; + } + + Type type; ///< The type of path + String foundPath; ///< The path where the file was found (might contain relative elements) + String uniqueIdentity; ///< The unique identity of the file on the path found }; class SourceLoc @@ -102,12 +137,13 @@ private: public: SourceLoc() : raw(0) - {} + { + } - SourceLoc( - SourceLoc const& loc) + SourceLoc(SourceLoc const& loc) : raw(loc.raw) - {} + { + } SLANG_FORCE_INLINE bool operator==(const ThisType& rhs) const { return raw == rhs.raw; } SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(raw == rhs.raw); } @@ -122,10 +158,7 @@ public: return result; } - bool isValid() const - { - return raw != 0; - } + bool isValid() const { return raw != 0; } SourceLoc& operator=(const ThisType& rhs) = default; }; @@ -137,43 +170,54 @@ inline SourceLoc operator+(SourceLoc loc, Int offset) // A range of locations in the input source struct SourceRange { - /// True if the loc is in the range. Range is inclusive on begin to end. - bool contains(SourceLoc loc) const { const auto rawLoc = loc.getRaw(); return rawLoc >= begin.getRaw() && rawLoc <= end.getRaw(); } - /// Get the total size + /// True if the loc is in the range. Range is inclusive on begin to end. + bool contains(SourceLoc loc) const + { + const auto rawLoc = loc.getRaw(); + return rawLoc >= begin.getRaw() && rawLoc <= end.getRaw(); + } + /// Get the total size UInt getSize() const { return UInt(end.getRaw() - begin.getRaw()); } - /// Get the offset of a loc in this range - int getOffset(SourceLoc loc) const { SLANG_ASSERT(contains(loc)); return int(loc.getRaw() - begin.getRaw()); } + /// Get the offset of a loc in this range + int getOffset(SourceLoc loc) const + { + SLANG_ASSERT(contains(loc)); + return int(loc.getRaw() - begin.getRaw()); + } - /// Convert an offset to a loc - SourceLoc getSourceLocFromOffset(uint32_t offset) const { SLANG_ASSERT(offset <= getSize()); return begin + Int(offset); } + /// Convert an offset to a loc + SourceLoc getSourceLocFromOffset(uint32_t offset) const + { + SLANG_ASSERT(offset <= getSize()); + return begin + Int(offset); + } - SourceRange() - {} + SourceRange() {} SourceRange(SourceLoc loc) - : begin(loc) - , end(loc) - {} + : begin(loc), end(loc) + { + } SourceRange(SourceLoc begin, SourceLoc end) - : begin(begin) - , end(end) - {} + : begin(begin), end(end) + { + } SourceLoc begin; SourceLoc end; }; /// Source maps associated with files are could be of different uses. We use the SourceMapKind -/// to indicate the usage. -/// -/// If the source map is obfuscated reasonable/desirable to ignore them on emit (if we didn't we leak information, -/// and we don't emit into the locations in the obfuscated intermediate "file"). +/// to indicate the usage. +/// +/// If the source map is obfuscated reasonable/desirable to ignore them on emit (if we didn't we +/// leak information, and we don't emit into the locations in the obfuscated intermediate "file"). enum class SourceMapKind { - Normal, ///< A regular source map - Obfuscated, ///< Obfuscated source map + Normal, ///< A regular source map + Obfuscated, ///< Obfuscated source map }; // Pre-declare @@ -181,113 +225,124 @@ struct SourceManager; // A logical or physical storage object for a range of input code // that has logically contiguous source locations. -class SourceFile +class SourceFile { public: - struct OffsetRange { - /// We need a value to indicate an invalid range. We can't use 0 as that is valid for an offset range - /// We can't use a negative number, and don't want to make signed so we get the full 32-bits. - /// So we just use the max value as invalid + /// We need a value to indicate an invalid range. We can't use 0 as that is valid for an + /// offset range We can't use a negative number, and don't want to make signed so we get the + /// full 32-bits. So we just use the max value as invalid static const uint32_t kInvalid = 0xffffffff; - /// True if the range is valid + /// True if the range is valid SLANG_FORCE_INLINE bool isValid() const { return end >= start && start != kInvalid; } - /// True if offset is within range (inclusively) - SLANG_FORCE_INLINE bool containsInclusive(uint32_t offset) const { return offset >= start && offset <= end; } + /// True if offset is within range (inclusively) + SLANG_FORCE_INLINE bool containsInclusive(uint32_t offset) const + { + return offset >= start && offset <= end; + } - /// Get the count + /// Get the count SLANG_FORCE_INLINE uint32_t getCount() const { return end - start; } - /// Return an invalid range. - static OffsetRange makeInvalid() { return OffsetRange{ kInvalid, kInvalid }; } + /// Return an invalid range. + static OffsetRange makeInvalid() { return OffsetRange{kInvalid, kInvalid}; } uint32_t start; uint32_t end; }; - /// Returns the line break offsets (in bytes from start of content) - /// Note that this is lazily evaluated - the line breaks are only calculated on the first request + /// Returns the line break offsets (in bytes from start of content) + /// Note that this is lazily evaluated - the line breaks are only calculated on the first + /// request const List& getLineBreakOffsets(); - /// Returns true if the offset is on the specified line - /// NOTE! If offsets are not fully setup (because we don't have source), will only be correct for lines that have offsets + /// Returns true if the offset is on the specified line + /// NOTE! If offsets are not fully setup (because we don't have source), will only be correct + /// for lines that have offsets bool isOffsetOnLine(uint32_t offset, Index lineIndex); - /// Get the line containing the offset. Requires that content is available, else will return an empty slice. + /// Get the line containing the offset. Requires that content is available, else will return an + /// empty slice. UnownedStringSlice getLineContainingOffset(uint32_t offset); - /// Get the line at the specified line index. Requires that content is available, else will return an empty slice. + /// Get the line at the specified line index. Requires that content is available, else will + /// return an empty slice. UnownedStringSlice getLineAtIndex(Index lineIndex); - /// Get the offset range at the specified line index. Works without content. + /// Get the offset range at the specified line index. Works without content. OffsetRange getOffsetRangeAtLineIndex(Index lineIndex); - /// Set the line break offsets + /// Set the line break offsets void setLineBreakOffsets(const uint32_t* offsets, UInt numOffsets); - /// Calculate the line based on the offset + /// Calculate the line based on the offset int calcLineIndexFromOffset(int offset); - /// Calculate the offset (in bytes) for a line + /// Calculate the offset (in bytes) for a line int calcColumnOffset(int line, int offset); - /// Given a line and offset (in bytes for the whole file), return the column index, taking into account tabs - /// and utf8 encoding. - /// Passing tabSize uses the default tab size (currently tab set to 1) + /// Given a line and offset (in bytes for the whole file), return the column index, taking into + /// account tabs and utf8 encoding. Passing tabSize uses the default tab size (currently tab set + /// to 1) int calcColumnIndex(int line, int offset, int tabSize = -1); - /// Get the content holding blob - ISlangBlob* getContentBlob() const { return m_contentBlob; } + /// Get the content holding blob + ISlangBlob* getContentBlob() const { return m_contentBlob; } - /// True if has full set content - bool hasContent() const { return m_contentBlob != nullptr; } + /// True if has full set content + bool hasContent() const { return m_contentBlob != nullptr; } - /// Get the content size - size_t getContentSize() const { return m_contentSize; } + /// Get the content size + size_t getContentSize() const { return m_contentSize; } - /// Get the content - const UnownedStringSlice& getContent() const { return m_content; } + /// Get the content + const UnownedStringSlice& getContent() const { return m_content; } - /// Get path info - const PathInfo& getPathInfo() const { return m_pathInfo; } + /// Get path info + const PathInfo& getPathInfo() const { return m_pathInfo; } - /// Set the content as a blob + /// Set the content as a blob void setContents(ISlangBlob* blob); - /// Set the content as a string + /// Set the content as a string void setContents(const String& content); - /// Calculate a display path -> can canonicalize if necessary + /// Calculate a display path -> can canonicalize if necessary String calcVerbosePath() const; - /// Get the source manager this was created on + /// Get the source manager this was created on SourceManager* getSourceManager() const { return m_sourceManager; } - /// Get the source map associated with this file. If it's set when doing - /// lookup for source locations, the source map will be used + /// Get the source map associated with this file. If it's set when doing + /// lookup for source locations, the source map will be used IBoxValue* getSourceMap() const { return m_sourceMap; } - /// Get the source map kind + /// Get the source map kind SourceMapKind getSourceMapKind() const { return m_sourceMapKind; } - /// Set a source map - void setSourceMap(IBoxValue* sourceMap, SourceMapKind sourceMapKind) { m_sourceMap = sourceMap; m_sourceMapKind = sourceMapKind; } + /// Set a source map + void setSourceMap(IBoxValue* sourceMap, SourceMapKind sourceMapKind) + { + m_sourceMap = sourceMap; + m_sourceMapKind = sourceMapKind; + } - /// Ctor + /// Ctor SourceFile(SourceManager* sourceManager, const PathInfo& pathInfo, size_t contentSize); - /// Dtor + /// Dtor ~SourceFile(); SHA1::Digest getDigest(); - protected: - - SourceManager* m_sourceManager; ///< The source manager this belongs to - PathInfo m_pathInfo; ///< The path The logical file path to report for locations inside this span. +protected: + SourceManager* m_sourceManager; ///< The source manager this belongs to + PathInfo + m_pathInfo; ///< The path The logical file path to report for locations inside this span. - ComPtr m_contentBlob; ///< A blob that owns the storage for the file contents. If nullptr, there is no contents - UnownedStringSlice m_content; ///< The actual contents of the file. - size_t m_contentSize; ///< The size of the actual contents + ComPtr m_contentBlob; ///< A blob that owns the storage for the file contents. If + ///< nullptr, there is no contents + UnownedStringSlice m_content; ///< The actual contents of the file. + size_t m_contentSize; ///< The size of the actual contents SHA1::Digest m_digest; @@ -296,7 +351,7 @@ public: // the input file: List m_lineBreakOffsets; - // If set then the locations in this file are really from locations from elsewhere, + // If set then the locations in this file are really from locations from elsewhere, // where the SourceMap specifies that mapping ComPtr> m_sourceMap; // What kind of source map it is (if there is one) @@ -305,17 +360,20 @@ public: enum class SourceLocType { - Nominal, ///< The normal interpretation which takes into account #line directives and source maps - Actual, ///< Ignores #line directives/source maps - and is the location as seen in the actual file - Emit, ///< Behaves the same as `Nominal` but ignores source maps. Used for Emit source locations. + Nominal, ///< The normal interpretation which takes into account #line directives and source + ///< maps + Actual, ///< Ignores #line directives/source maps - and is the location as seen in the actual + ///< file + Emit, ///< Behaves the same as `Nominal` but ignores source maps. Used for Emit source + ///< locations. }; // A source location in a format a human might like to see struct HumaneSourceLoc { PathInfo pathInfo = PathInfo::makeUnknown(); - Int line = 0; - Int column = 0; + Int line = 0; + Int column = 0; }; // Same as HumaneSourceLoc but stores the path only as a handle. @@ -326,85 +384,95 @@ struct HandleSourceLoc Int column = 0; }; -/* A SourceView maps to a single span of SourceLoc range and is equivalent to a single include or more precisely use of a source file. -It is distinct from a SourceFile - because a SourceFile may be included multiple times, with different interpretations (depending -on #defines for example). -*/ +/* A SourceView maps to a single span of SourceLoc range and is equivalent to a single include or +more precisely use of a source file. It is distinct from a SourceFile - because a SourceFile may be +included multiple times, with different interpretations (depending on #defines for example). +*/ class SourceView { - public: - +public: // Each entry represents some contiguous span of locations that // all map to the same logical file. struct Entry { - /// True if this resets the line numbering. It is distinct from a m_lineAdjust being 0, because it also means the path returns to the default. + /// True if this resets the line numbering. It is distinct from a m_lineAdjust being 0, + /// because it also means the path returns to the default. bool isDefault() const { return m_pathHandle == StringSlicePool::Handle(0); } - SourceLoc m_startLoc; ///< Where does this entry begin? - StringSlicePool::Handle m_pathHandle; ///< What is the presumed path for this entry. If 0 it means there is no path. - int32_t m_lineAdjust; ///< Adjustment to apply to source line numbers when printing presumed locations. Relative to the line number in the underlying file. + SourceLoc m_startLoc; ///< Where does this entry begin? + StringSlicePool::Handle m_pathHandle; ///< What is the presumed path for this entry. If 0 it + ///< means there is no path. + int32_t m_lineAdjust; ///< Adjustment to apply to source line numbers when printing presumed + ///< locations. Relative to the line number in the underlying file. }; - /// Given a sourceLoc finds the entry associated with it. If returns -1 then no entry is - /// associated with this location, and therefore the location should be interpreted as an offset - /// into the underlying sourceFile. + /// Given a sourceLoc finds the entry associated with it. If returns -1 then no entry is + /// associated with this location, and therefore the location should be interpreted as an offset + /// into the underlying sourceFile. int findEntryIndex(SourceLoc sourceLoc) const; - /// Add a line directive for this view. The directiveLoc must of course be in this SourceView - /// The path handle, must have been constructed on the SourceManager associated with the view - /// NOTE! Directives are assumed to be added IN ORDER during parsing such that every directiveLoc > previous + /// Add a line directive for this view. The directiveLoc must of course be in this SourceView + /// The path handle, must have been constructed on the SourceManager associated with the view + /// NOTE! Directives are assumed to be added IN ORDER during parsing such that every + /// directiveLoc > previous void addLineDirective(SourceLoc directiveLoc, StringSlicePool::Handle pathHandle, int line); void addLineDirective(SourceLoc directiveLoc, const String& path, int line); - /// Removes any corrections on line numbers and reverts to the source files path + /// Removes any corrections on line numbers and reverts to the source files path void addDefaultLineDirective(SourceLoc directiveLoc); - /// Get the range that this view applies to + /// Get the range that this view applies to const SourceRange& getRange() const { return m_range; } - /// Get the entries + /// Get the entries const List& getEntries() const { return m_entries; } - /// Set the entries list - void setEntries(const Entry* entries, UInt numEntries) { m_entries.clear(); m_entries.addRange(entries, numEntries); } + /// Set the entries list + void setEntries(const Entry* entries, UInt numEntries) + { + m_entries.clear(); + m_entries.addRange(entries, numEntries); + } - /// Get the source file holds the contents this view + /// Get the source file holds the contents this view SourceFile* getSourceFile() const { return m_sourceFile; } - /// Get the source manager + /// Get the source manager SourceManager* getSourceManager() const { return m_sourceFile->getSourceManager(); } - /// Get the associated 'content' (the source text) + /// Get the associated 'content' (the source text) const UnownedStringSlice& getContent() const { return m_sourceFile->getContent(); } - /// Get the size of the content + /// Get the size of the content size_t getContentSize() const { return m_sourceFile->getContentSize(); } - /// Get the humane location - /// Type determines if the location wanted is the original, or the 'normal' (which modifys behavior based on #line directives) + /// Get the humane location + /// Type determines if the location wanted is the original, or the 'normal' (which modifys + /// behavior based on #line directives) HumaneSourceLoc getHumaneLoc(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); - /// Get the humane location, but store the path as a handle + /// Get the humane location, but store the path as a handle HandleSourceLoc getHandleLoc(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); - /// Get the path associated with a location + /// Get the path associated with a location PathInfo getPathInfo(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); - /// Get the initiating source location - that is the source location that caused the this SourceView to be created - /// Can be SourceLoc(0) if there is no initiating location. - /// For example for a #include - the view's initiating source loc for the view that is the contents of the view - /// will be the location of the #include in the source. - /// For the original source file (ie not an include) - the view will have an initiating source loc of SourceLoc(0) + /// Get the initiating source location - that is the source location that caused the this + /// SourceView to be created Can be SourceLoc(0) if there is no initiating location. For example + /// for a #include - the view's initiating source loc for the view that is the contents of the + /// view will be the location of the #include in the source. For the original source file (ie + /// not an include) - the view will have an initiating source loc of SourceLoc(0) SourceLoc getInitiatingSourceLoc() const { return m_initiatingSourceLoc; } - /// Gets the pathInfo for this view. It may be different from the m_sourceFile's if the path has been - /// overridden by m_viewPath + /// Gets the pathInfo for this view. It may be different from the m_sourceFile's if the path has + /// been overridden by m_viewPath PathInfo getViewPathInfo() const; - /// Ctor - SourceView(SourceFile* sourceFile, SourceRange range, const String* viewPath, SourceLoc initiatingSourceLoc): - m_range(range), - m_sourceFile(sourceFile), - m_initiatingSourceLoc(initiatingSourceLoc) + /// Ctor + SourceView( + SourceFile* sourceFile, + SourceRange range, + const String* viewPath, + SourceLoc initiatingSourceLoc) + : m_range(range), m_sourceFile(sourceFile), m_initiatingSourceLoc(initiatingSourceLoc) { if (viewPath) { @@ -412,116 +480,122 @@ class SourceView } } - protected: - /// Get the pathInfo from a string handle. If it's 0, it will return the _getPathInfo +protected: + /// Get the pathInfo from a string handle. If it's 0, it will return the _getPathInfo PathInfo _getPathInfoFromHandle(StringSlicePool::Handle pathHandle) const; - + SlangResult _findSourceMapLoc(SourceLoc loc, SourceLocType type, HandleSourceLoc& outLoc); - String m_viewPath; ///< Path to this view. If empty the path is the path to the SourceView + String m_viewPath; ///< Path to this view. If empty the path is the path to the SourceView - SourceLoc m_initiatingSourceLoc; ///< An optional source loc that defines where this view was initiated from. SourceLoc(0) if not defined. + SourceLoc m_initiatingSourceLoc; ///< An optional source loc that defines where this view was + ///< initiated from. SourceLoc(0) if not defined. - SourceRange m_range; ///< The range that this SourceView applies to - SourceFile* m_sourceFile; ///< The source file. Can hold the line breaks - List m_entries; ///< An array entries describing how we should interpret a range, starting from the start location. + SourceRange m_range; ///< The range that this SourceView applies to + SourceFile* m_sourceFile; ///< The source file. Can hold the line breaks + List m_entries; ///< An array entries describing how we should interpret a range, + ///< starting from the start location. }; struct SourceManager { - // Initialize a source manager, with an optional parent + // Initialize a source manager, with an optional parent void initialize(SourceManager* parent, ISlangFileSystemExt* fileSystemExt); - /// Allocate a range of SourceLoc locations, these can be used to identify a specific location in the source + /// Allocate a range of SourceLoc locations, these can be used to identify a specific location + /// in the source SourceRange allocateSourceRange(UInt size); - /// Returns the loc for start of next allocation + /// Returns the loc for start of next allocation SourceLoc getNextRangeStart() const { return m_nextLoc; } - /// Create a SourceFile defined with the specified path, and content held within a blob + /// Create a SourceFile defined with the specified path, and content held within a blob SourceFile* createSourceFileWithSize(const PathInfo& pathInfo, size_t contentSize); SourceFile* createSourceFileWithString(const PathInfo& pathInfo, const String& contents); SourceFile* createSourceFileWithBlob(const PathInfo& pathInfo, ISlangBlob* blob); - /// Get the humane source location + /// Get the humane source location HumaneSourceLoc getHumaneLoc(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); - /// Get the path associated with a location + /// Get the path associated with a location PathInfo getPathInfo(SourceLoc loc, SourceLocType type = SourceLocType::Nominal); - /// Create a new source view from a file - /// @param sourceFile is the source file that contains the source - /// @param pathInfo is path used to read the file from - /// @param initiatingSourceLoc the (optional) location in the source that led the the creation of this view. If there isn't an initiating source location pass SourceLoc(0)s - SourceView* createSourceView(SourceFile* sourceFile, const PathInfo* pathInfo, SourceLoc initiatingSourceLoc); - - /// Find a view by a source file location. - /// If not found in this manager will look in the parent SourceManager - /// Returns nullptr if not found. + /// Create a new source view from a file + /// @param sourceFile is the source file that contains the source + /// @param pathInfo is path used to read the file from + /// @param initiatingSourceLoc the (optional) location in the source that led the the creation + /// of this view. If there isn't an initiating source location pass SourceLoc(0)s + SourceView* createSourceView( + SourceFile* sourceFile, + const PathInfo* pathInfo, + SourceLoc initiatingSourceLoc); + + /// Find a view by a source file location. + /// If not found in this manager will look in the parent SourceManager + /// Returns nullptr if not found. SourceView* findSourceViewRecursively(SourceLoc loc) const; - /// Find the SourceView associated with this manager for a specified location - /// Returns nullptr if not found. + /// Find the SourceView associated with this manager for a specified location + /// Returns nullptr if not found. SourceView* findSourceView(SourceLoc loc) const; - /// Searches this manager, and then the parent to see if can find a match for path. - /// If not found returns nullptr. + /// Searches this manager, and then the parent to see if can find a match for path. + /// If not found returns nullptr. SourceFile* findSourceFileRecursively(const String& uniqueIdentity) const; - /// Find if the source file is defined on this manager. + /// Find if the source file is defined on this manager. SourceFile* findSourceFile(const String& uniqueIdentity) const; - /// Find a source file by path. + /// Find a source file by path. SourceFile* findSourceFileByPath(const String& name) const; - /// Find a source file by path recursively. + /// Find a source file by path recursively. SourceFile* findSourceFileByPathRecursively(const String& name) const; - /// Searches this manager, and then the parent to see if can find a match + /// Searches this manager, and then the parent to see if can find a match SourceFile* findSourceFileByContentRecursively(const char* text); - /// Find the source file that contains *the memory* text points to. + /// Find the source file that contains *the memory* text points to. SourceFile* findSourceFileByContent(const char* text) const; - - /// Get the file system associated with this source manager - ISlangFileSystemExt* getFileSystemExt() const { return m_fileSystemExt; } - /// Get the file system associated with this source manager - void setFileSystemExt(ISlangFileSystemExt* fileSystemExt) { m_fileSystemExt = fileSystemExt; } - /// Add a source file, uniqueIdentity must be unique for this manager AND any parents + /// Get the file system associated with this source manager + ISlangFileSystemExt* getFileSystemExt() const { return m_fileSystemExt; } + /// Get the file system associated with this source manager + void setFileSystemExt(ISlangFileSystemExt* fileSystemExt) { m_fileSystemExt = fileSystemExt; } + + /// Add a source file, uniqueIdentity must be unique for this manager AND any parents void addSourceFile(const String& uniqueIdentity, SourceFile* sourceFile); void addSourceFileIfNotExist(const String& uniqueIdentity, SourceFile* sourceFile); - /// Get the slice pool + /// Get the slice pool StringSlicePool& getStringSlicePool() { return m_slicePool; } - /// Get the source range for just this manager - /// Caution - the range will change if allocations are made to this manager. - SourceRange getSourceRange() const { return SourceRange(m_startLoc, m_nextLoc); } - - /// Get the parent manager to this manager. Returns nullptr if there isn't any. + /// Get the source range for just this manager + /// Caution - the range will change if allocations are made to this manager. + SourceRange getSourceRange() const { return SourceRange(m_startLoc, m_nextLoc); } + + /// Get the parent manager to this manager. Returns nullptr if there isn't any. SourceManager* getParent() const { return m_parent; } - /// A memory arena to hold allocations that are in scope for the same time as SourceManager - MemoryArena* getMemoryArena() { return &m_memoryArena; } + /// A memory arena to hold allocations that are in scope for the same time as SourceManager + MemoryArena* getMemoryArena() { return &m_memoryArena; } - /// Allocate a string slice + /// Allocate a string slice UnownedStringSlice allocateStringSlice(const UnownedStringSlice& slice); - /// Get all of the source files + /// Get all of the source files const List& getSourceFiles() const { return m_sourceFiles; } - /// Get the source views + /// Get the source views const List& getSourceViews() const { return m_sourceViews; } - /// Resets state. Will release all views/source + /// Resets state. Will release all views/source void reset(); - SourceManager() : - m_memoryArena(2048), - m_slicePool(StringSlicePool::Style::Default) - {} + SourceManager() + : m_memoryArena(2048), m_slicePool(StringSlicePool::Style::Default) + { + } ~SourceManager(); - protected: - +protected: void _resetLoc(); void _resetSource(); @@ -536,7 +610,8 @@ struct SourceManager // The location to be used by the next source file to be loaded SourceLoc m_nextLoc; - // All of the SourceViews constructed on this SourceManager. These are held in increasing order of range, so can find by doing a binary chop. + // All of the SourceViews constructed on this SourceManager. These are held in increasing order + // of range, so can find by doing a binary chop. List m_sourceViews; // All of the SourceFiles constructed on this SourceManager. This owns the SourceFile. List m_sourceFiles; diff --git a/source/compiler-core/slang-source-map.cpp b/source/compiler-core/slang-source-map.cpp index 533c6bde0..9c38e876f 100644 --- a/source/compiler-core/slang-source-map.cpp +++ b/source/compiler-core/slang-source-map.cpp @@ -1,6 +1,7 @@ #include "slang-source-map.h" -namespace Slang { +namespace Slang +{ void SourceMap::clear() { @@ -35,7 +36,10 @@ void SourceMap::swapWith(ThisType& rhs) m_slicePool.swapWith(rhs.m_slicePool); } -static bool _areEqual(const List& a, const List& b, const List& bToAMap) +static bool _areEqual( + const List& a, + const List& b, + const List& bToAMap) { const auto count = a.getCount(); if (count != b.getCount()) @@ -57,16 +61,20 @@ static bool _areEqual(const List& a, const List& bToAMap) +static bool _areEqual( + const SourceMap::Entry& a, + const SourceMap::Entry& b, + const List& bToAMap) { - return a.generatedColumn == b.generatedColumn && - a.sourceLine == b.sourceLine && - a.sourceColumn == b.sourceColumn && - a.sourceFileIndex == bToAMap[b.sourceFileIndex] && - a.nameIndex == bToAMap[b.nameIndex]; + return a.generatedColumn == b.generatedColumn && a.sourceLine == b.sourceLine && + a.sourceColumn == b.sourceColumn && a.sourceFileIndex == bToAMap[b.sourceFileIndex] && + a.nameIndex == bToAMap[b.nameIndex]; } -static bool _areEqual(const List& a, const List&b, const List& bToAMap) +static bool _areEqual( + const List& a, + const List& b, + const List& bToAMap) { const auto count = a.getCount(); if (count != b.getCount()) @@ -92,8 +100,7 @@ bool SourceMap::operator==(const ThisType& rhs) const return true; } - if (m_file != rhs.m_file || - m_sourceRoot != rhs.m_sourceRoot || + if (m_file != rhs.m_file || m_sourceRoot != rhs.m_sourceRoot || m_lineStarts != rhs.m_lineStarts) { return false; @@ -102,21 +109,19 @@ bool SourceMap::operator==(const ThisType& rhs) const if (m_slicePool == rhs.m_slicePool) { // If the slice pools are the same we can just compare indices directly - return m_sources == rhs.m_sources && - m_sourcesContent == rhs.m_sourcesContent && - m_names == rhs.m_names && - m_lineEntries == rhs.m_lineEntries; + return m_sources == rhs.m_sources && m_sourcesContent == rhs.m_sourcesContent && + m_names == rhs.m_names && m_lineEntries == rhs.m_lineEntries; } else { // Otherwise we need to remap the indices - // Maps a pool handle from the rhs source map to the + // Maps a pool handle from the rhs source map to the List rhsMap; Count count = rhs.m_slicePool.getSlicesCount(); rhsMap.setCount(count); - + const auto startIndex = rhs.m_slicePool.getFirstAddedIndex(); // Work out the map @@ -128,9 +133,9 @@ bool SourceMap::operator==(const ThisType& rhs) const // Do the comparison taking into account the mapping. return _areEqual(m_sources, rhs.m_sources, rhsMap) && - _areEqual(m_sourcesContent, rhs.m_sourcesContent, rhsMap) && - _areEqual(m_names, rhs.m_names, rhsMap) && - _areEqual(m_lineEntries, rhs.m_lineEntries, rhsMap); + _areEqual(m_sourcesContent, rhs.m_sourcesContent, rhsMap) && + _areEqual(m_names, rhs.m_names, rhsMap) && + _areEqual(m_lineEntries, rhs.m_lineEntries, rhsMap); } } @@ -139,7 +144,7 @@ void SourceMap::advanceToLine(Index nextLineIndex) const Count currentLineIndex = getGeneratedLineCount() - 1; SLANG_ASSERT(nextLineIndex >= currentLineIndex); - + if (nextLineIndex <= currentLineIndex) { return; @@ -147,7 +152,7 @@ void SourceMap::advanceToLine(Index nextLineIndex) const auto lastEntryIndex = m_lineEntries.getCount(); - // For all the new entries they will need to point to the end + // For all the new entries they will need to point to the end m_lineStarts.growToCount(nextLineIndex + 1); Index* starts = m_lineStarts.getBuffer(); diff --git a/source/compiler-core/slang-source-map.h b/source/compiler-core/slang-source-map.h index 4060fadb8..73952225a 100644 --- a/source/compiler-core/slang-source-map.h +++ b/source/compiler-core/slang-source-map.h @@ -1,21 +1,20 @@ #ifndef SLANG_COMPILER_CORE_SOURCE_MAP_H #define SLANG_COMPILER_CORE_SOURCE_MAP_H -#include "slang.h" - -#include "../core/slang-string.h" #include "../core/slang-list.h" - #include "../core/slang-string-slice-pool.h" +#include "../core/slang-string.h" +#include "slang.h" -namespace Slang { +namespace Slang +{ -class SourceMap +class SourceMap { public: typedef SourceMap ThisType; - SLANG_CLASS_GUID(0x731383ea, 0xe516, 0x4cc3, { 0xa6, 0xcf, 0x37, 0xd2, 0x8c, 0x24, 0x5c, 0x5e }); + SLANG_CLASS_GUID(0x731383ea, 0xe516, 0x4cc3, {0xa6, 0xcf, 0x37, 0xd2, 0x8c, 0x24, 0x5c, 0x5e}); struct Entry { @@ -33,73 +32,71 @@ public: bool operator==(const ThisType& rhs) const { return generatedColumn == rhs.generatedColumn && - sourceFileIndex == rhs.sourceFileIndex && - sourceLine == rhs.sourceLine && - sourceColumn == rhs.sourceColumn && - nameIndex == rhs.nameIndex; + sourceFileIndex == rhs.sourceFileIndex && sourceLine == rhs.sourceLine && + sourceColumn == rhs.sourceColumn && nameIndex == rhs.nameIndex; } SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } // Note! All column/line are zero indexed - Index generatedColumn; ///< The generated column - Index sourceFileIndex; ///< The index into the source name/contents - Index sourceLine; ///< The line number in the originating source - Index sourceColumn; ///< The column number in the originating source - Index nameIndex; ///< Name index + Index generatedColumn; ///< The generated column + Index sourceFileIndex; ///< The index into the source name/contents + Index sourceLine; ///< The line number in the originating source + Index sourceColumn; ///< The column number in the originating source + Index nameIndex; ///< Name index }; - /// Get the total number of generated lines + /// Get the total number of generated lines Count getGeneratedLineCount() const { return m_lineStarts.getCount(); } - /// Get the entries on the line + /// Get the entries on the line SLANG_FORCE_INLINE ConstArrayView getEntriesForLine(Index generatedLine) const; - - /// Advance to the specified line index. - /// It is an error to specify a line *before* the current line. It should either be the current - /// output line or a later output line. Interveining lines will be set as empty + + /// Advance to the specified line index. + /// It is an error to specify a line *before* the current line. It should either be the current + /// output line or a later output line. Interveining lines will be set as empty void advanceToLine(Index lineIndex); - /// Add an entry to the current line + /// Add an entry to the current line void addEntry(const Entry& entry) { m_lineEntries.add(entry); } - /// Given the slice returns the index + /// Given the slice returns the index Index getSourceFileIndex(const UnownedStringSlice& slice); - /// Get the name index + /// Get the name index Index getNameIndex(const UnownedStringSlice& slice); - /// Given a row and col index, find the closest entry - /// NOTE! Zero indexed line and column. + /// Given a row and col index, find the closest entry + /// NOTE! Zero indexed line and column. Index findEntry(Index lineIndex, Index colIndex) const; - /// Given an entry index return the entry - const Entry& getEntryByIndex(Index i) const {return m_lineEntries[i]; } + /// Given an entry index return the entry + const Entry& getEntryByIndex(Index i) const { return m_lineEntries[i]; } - /// Given the sourceFileIndex return the name + /// Given the sourceFileIndex return the name UnownedStringSlice getSourceFileName(Index sourceFileIndex) const; - /// Clear the contents of the source map + /// Clear the contents of the source map void clear(); - /// Swap this with rhs + /// Swap this with rhs void swapWith(ThisType& rhs); - /// == - /// - /// Note that equality requires that entries for a line must be *in the same order* - /// even though strictly speaking with different orders could be considered equivalent. + /// == + /// + /// Note that equality requires that entries for a line must be *in the same order* + /// even though strictly speaking with different orders could be considered equivalent. bool operator==(const ThisType& rhs) const; - /// != + /// != bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - /// Ctor - SourceMap(): - m_slicePool(StringSlicePool::Style::Default) + /// Ctor + SourceMap() + : m_slicePool(StringSlicePool::Style::Default) { clear(); } - /// Copy Ctor + /// Copy Ctor SourceMap(const ThisType& rhs) = default; - /// Assignment + /// Assignment ThisType& operator=(const ThisType& rhs) = default; String m_file; @@ -107,10 +104,10 @@ public: List m_sources; - /// Storage for the contents. Can be unset null to indicate not set. + /// Storage for the contents. Can be unset null to indicate not set. List m_sourcesContent; - - /// The names + + /// The names List m_names; List m_lineStarts; @@ -120,13 +117,16 @@ public: }; // ------------------------------------------------------------- -SLANG_FORCE_INLINE ConstArrayView SourceMap::getEntriesForLine(Index generatedLine) const +SLANG_FORCE_INLINE ConstArrayView SourceMap::getEntriesForLine( + Index generatedLine) const { SLANG_ASSERT(generatedLine >= 0 && generatedLine < m_lineStarts.getCount()); const Index start = m_lineStarts[generatedLine]; - const Index end = (generatedLine + 1 >= m_lineStarts.getCount()) ? m_lineEntries.getCount() : m_lineStarts[generatedLine + 1]; + const Index end = (generatedLine + 1 >= m_lineStarts.getCount()) + ? m_lineEntries.getCount() + : m_lineStarts[generatedLine + 1]; const auto entries = m_lineEntries.begin(); diff --git a/source/compiler-core/slang-spirv-core-grammar.cpp b/source/compiler-core/slang-spirv-core-grammar.cpp index 0660954fa..8b5e79071 100644 --- a/source/compiler-core/slang-spirv-core-grammar.cpp +++ b/source/compiler-core/slang-spirv-core-grammar.cpp @@ -2,8 +2,9 @@ #include "../core/slang-rtti-util.h" #include "../core/slang-string-util.h" -#include "slang-json-native.h" #include "slang-core-diagnostics.h" +#include "slang-json-native.h" + #include namespace Slang @@ -22,8 +23,7 @@ struct InstructionPrintingClass SLANG_MAKE_STRUCT_RTTI_INFO( InstructionPrintingClass, SLANG_RTTI_FIELD(tag), - SLANG_OPTIONAL_RTTI_FIELD(heading) -); + SLANG_OPTIONAL_RTTI_FIELD(heading)); struct Operand { @@ -35,7 +35,7 @@ SLANG_MAKE_STRUCT_RTTI_INFO( Operand, SLANG_RTTI_FIELD(kind), SLANG_OPTIONAL_RTTI_FIELD(quantifier) - //SLANG_RTTI_FIELD(name), + // SLANG_RTTI_FIELD(name), ); struct Instruction @@ -52,8 +52,7 @@ SLANG_MAKE_STRUCT_RTTI_INFO( SLANG_RTTI_FIELD_IMPL(class_, "class", 0), SLANG_RTTI_FIELD(opcode), SLANG_OPTIONAL_RTTI_FIELD(capabilities), - SLANG_OPTIONAL_RTTI_FIELD(operands) -); + SLANG_OPTIONAL_RTTI_FIELD(operands)); struct Enumerant { @@ -88,8 +87,7 @@ SLANG_MAKE_STRUCT_RTTI_INFO( OperandKind, SLANG_RTTI_FIELD(category), SLANG_RTTI_FIELD(kind), - SLANG_OPTIONAL_RTTI_FIELD(enumerants) -); + SLANG_OPTIONAL_RTTI_FIELD(enumerants)); struct SPIRVSpec { @@ -111,47 +109,44 @@ SLANG_MAKE_STRUCT_RTTI_INFO( // SLANG_RTTI_FIELD(revision) SLANG_RTTI_FIELD(instruction_printing_class), SLANG_RTTI_FIELD(instructions), - SLANG_RTTI_FIELD(operand_kinds) -); + SLANG_RTTI_FIELD(operand_kinds)); static Dictionary operandKindToDict( - JSONContainer& container, - DiagnosticSink& sink, - const OperandKind& k) + JSONContainer& container, + DiagnosticSink& sink, + const OperandKind& k) { Dictionary dict; dict.reserve(k.enumerants.getCount()); - for(const auto& e : k.enumerants) + for (const auto& e : k.enumerants) { SpvWord valueInt = 0; - switch(e.value.getKind()) + switch (e.value.getKind()) { - case JSONValue::Kind::Integer: + case JSONValue::Kind::Integer: { // TODO: Range check here? valueInt = SpvWord(container.asInteger(e.value)); break; } - case JSONValue::Kind::String: + case JSONValue::Kind::String: { Int i = 0; const auto str = container.getString(e.value); - if(SLANG_FAILED(StringUtil::parseInt(str, i))) + if (SLANG_FAILED(StringUtil::parseInt(str, i))) sink.diagnose( e.value.loc, MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "Expected an integer value" - ); + "Expected an integer value"); // TODO: Range check here? valueInt = SpvWord(i); break; - } - default: - sink.diagnose( - e.value.loc, - MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "Expected an integer value (or a string with an integer inside)" - ); + } + default: + sink.diagnose( + e.value.loc, + MiscDiagnostics::spirvCoreGrammarJSONParseFailure, + "Expected an integer value (or a string with an integer inside)"); } dict.add(e.enumerant, valueInt); @@ -166,7 +161,9 @@ static Dictionary operandKindToDict( // // // -RefPtr SPIRVCoreGrammarInfo::loadFromJSON(SourceView& source, DiagnosticSink& sink) +RefPtr SPIRVCoreGrammarInfo::loadFromJSON( + SourceView& source, + DiagnosticSink& sink) { // // Load the JSON @@ -182,14 +179,13 @@ RefPtr SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour SLANG_RETURN_NULL_ON_FAIL(parser.parse(&lexer, &source, &builder, &sink)); JSONToNativeConverter converter(&container, &typeMap, &sink); SPIRVSpec spec; - if(SLANG_FAILED(converter.convert(builder.getRootValue(), &spec))) + if (SLANG_FAILED(converter.convert(builder.getRootValue(), &spec))) { // TODO: not having a source loc here is not great... sink.diagnoseWithoutSourceView( SourceLoc{}, MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "Failed to match SPIR-V grammar JSON to the expected schema" - ); + "Failed to match SPIR-V grammar JSON to the expected schema"); return nullptr; } @@ -200,42 +196,42 @@ RefPtr SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour res->operandKinds.dict.reserve(spec.operand_kinds.getCount()); uint32_t operandKindIndex = 0; - for(const auto& c : spec.operand_kinds) + for (const auto& c : spec.operand_kinds) { - if(operandKindIndex > std::numeric_limits::max()) + if (operandKindIndex > std::numeric_limits::max()) { sink.diagnoseWithoutSourceView( SourceLoc{}, MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "Too many enum categories, expected fewer than 256" - ); + "Too many enum categories, expected fewer than 256"); } - res->operandKinds.dict.add(c.kind, {static_cast(operandKindIndex)}); + res->operandKinds.dict.add( + c.kind, + {static_cast(operandKindIndex)}); operandKindIndex++; } // It's important we reserve the memory now, as we require the iterators to // be stable, as references to them are maintained by the OpInfo structs. Index totalNumOperands = 0; - for(const auto& i : spec.instructions) + for (const auto& i : spec.instructions) totalNumOperands += i.operands.getCapacity(); res->operandTypesStorage.reserve(totalNumOperands); res->opcodes.dict.reserve(spec.instructions.getCount()); - for(const auto& i : spec.instructions) + for (const auto& i : spec.instructions) { res->opcodes.dict.add(i.opname, SpvOp(i.opcode)); - const auto class_ = - i.class_ == "Type-Declaration" ? OpInfo::TypeDeclaration - : i.class_ == "Constant-Creation" ? OpInfo::ConstantCreation - : i.class_ == "Debug" ? OpInfo::Debug - : OpInfo::Other; + const auto class_ = i.class_ == "Type-Declaration" ? OpInfo::TypeDeclaration + : i.class_ == "Constant-Creation" ? OpInfo::ConstantCreation + : i.class_ == "Debug" ? OpInfo::Debug + : OpInfo::Other; - const auto resultTypeIndex - = i.operands.findFirstIndex([](const auto& o){return o.kind == "IdResultType";}); - const auto resultIdIndex - = i.operands.findFirstIndex([](const auto& o){return o.kind == "IdResult";}); + const auto resultTypeIndex = + i.operands.findFirstIndex([](const auto& o) { return o.kind == "IdResultType"; }); + const auto resultIdIndex = + i.operands.findFirstIndex([](const auto& o) { return o.kind == "IdResult"; }); SLANG_ASSERT(resultTypeIndex >= -1 || resultTypeIndex <= 0); SLANG_ASSERT(resultIdIndex >= -1 || resultTypeIndex <= 1); @@ -243,9 +239,9 @@ RefPtr SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour uint16_t maxOperandCount = 0; uint16_t numOperandTypes = 0; const OperandKind* operandTypes = res->operandTypesStorage.end(); - for(const auto& o : i.operands) + for (const auto& o : i.operands) { - if(maxOperandCount == 0xffff) + if (maxOperandCount == 0xffff) { // We are about to overflow maxWordCount, either someone has // put 2^16 operands in the json, or we have a "*" quantified @@ -254,18 +250,16 @@ RefPtr SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour sink.diagnoseWithoutSourceView( SourceLoc{}, MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "\"*\"-qualified operand wasn't the last operand" - ); + "\"*\"-qualified operand wasn't the last operand"); } const auto catIndex = res->operandKinds.lookup(o.kind); - if(!catIndex) + if (!catIndex) { sink.diagnoseWithoutSourceView( SourceLoc{}, MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "Operand references a kind which doesn't exist" - ); + "Operand references a kind which doesn't exist"); continue; } @@ -274,24 +268,23 @@ RefPtr SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour // The number of "ImageOperands" is dependent on the bitmask // operand, for our purposes treat them as unbounded - if(o.quantifier == "*" || o.kind == "ImageOperands") + if (o.quantifier == "*" || o.kind == "ImageOperands") { maxOperandCount = 0xffff; } - else if(o.quantifier == "?") + else if (o.quantifier == "?") { maxOperandCount++; } - else if(o.quantifier == "") + else if (o.quantifier == "") { // This catches the case where an "?" or "*" qualified operand // appears before any unqualified operands - if(minOperandCount != maxOperandCount) + if (minOperandCount != maxOperandCount) sink.diagnoseWithoutSourceView( SourceLoc{}, MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "\"*\" or \"?\" operand appeared before an unqualified operand" - ); + "\"*\" or \"?\" operand appeared before an unqualified operand"); minOperandCount++; maxOperandCount++; } @@ -300,31 +293,30 @@ RefPtr SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour sink.diagnose( SourceLoc{}, MiscDiagnostics::spirvCoreGrammarJSONParseFailure, - "quantifier wasn't empty, * or ?" - ); + "quantifier wasn't empty, * or ?"); } } // There are duplicate opcodes in the json (for renamed instructions, // or the same instruction with different capabilities), for now just // keep the first one. - res->opInfos.dict.addIfNotExists(SpvOp(i.opcode), { - class_, - static_cast(resultTypeIndex), - static_cast(resultIdIndex), - minOperandCount, - maxOperandCount, - numOperandTypes, - operandTypes - }); + res->opInfos.dict.addIfNotExists( + SpvOp(i.opcode), + {class_, + static_cast(resultTypeIndex), + static_cast(resultIdIndex), + minOperandCount, + maxOperandCount, + numOperandTypes, + operandTypes}); res->opNames.dict.addIfNotExists(SpvOp(i.opcode), i.opname); } - for(const auto& k : spec.operand_kinds) + for (const auto& k : spec.operand_kinds) { const auto kindIndex = res->operandKinds.dict.getValue(k.kind); const auto d = operandKindToDict(container, sink, k); - for(const auto& [n, v] : d) + for (const auto& [n, v] : d) { // Add the string to this slice pool as we'll be taking ownership // of it shortly but don't want to invalidate it in the meantime. @@ -336,17 +328,17 @@ RefPtr SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour res->operandKindNames.dict.add(kindIndex, k.kind); - if(k.kind == "Capability") - for(const auto& [n, v] : d) + if (k.kind == "Capability") + for (const auto& [n, v] : d) res->capabilities.dict.add(n, SpvCapability(v)); // If this starts with Id, and the suffix is also an operand kind, // assume that this is an Id wrapper - if(k.kind.startsWith("Id")) + if (k.kind.startsWith("Id")) { - const UnownedStringSlice underneathIdKind{k.kind.begin()+2, k.kind.end()}; + const UnownedStringSlice underneathIdKind{k.kind.begin() + 2, k.kind.end()}; OperandKind targetIndex; - if(res->operandKinds.dict.tryGetValue(underneathIdKind, targetIndex)) + if (res->operandKinds.dict.tryGetValue(underneathIdKind, targetIndex)) res->operandKindUnderneathIds.dict.add(kindIndex, targetIndex); } } @@ -354,4 +346,4 @@ RefPtr SPIRVCoreGrammarInfo::loadFromJSON(SourceView& sour res->strings.swapWith(container.getStringSlicePool()); return res; } -} +} // namespace Slang diff --git a/source/compiler-core/slang-spirv-core-grammar.h b/source/compiler-core/slang-spirv-core-grammar.h index d78a339f1..e91caa79a 100644 --- a/source/compiler-core/slang-spirv-core-grammar.h +++ b/source/compiler-core/slang-spirv-core-grammar.h @@ -1,148 +1,147 @@ #pragma once +#include "../core/slang-dictionary.h" #include "../core/slang-smart-pointer.h" -#include "../core/slang-string.h" #include "../core/slang-string-slice-pool.h" -#include "../core/slang-dictionary.h" - -#include +#include "../core/slang-string.h" #include +#include namespace Slang { - using SpvWord = uint32_t; - class DiagnosticSink; - class SourceView; +using SpvWord = uint32_t; +class DiagnosticSink; +class SourceView; - struct SPIRVCoreGrammarInfo : public RefObject - { - static RefPtr loadFromJSON(SourceView& source, DiagnosticSink& sink); - static RefPtr& getEmbeddedVersion(); - static inline void freeEmbeddedGrammerInfo() { getEmbeddedVersion() = nullptr; } +struct SPIRVCoreGrammarInfo : public RefObject +{ + static RefPtr loadFromJSON(SourceView& source, DiagnosticSink& sink); + static RefPtr& getEmbeddedVersion(); + static inline void freeEmbeddedGrammerInfo() { getEmbeddedVersion() = nullptr; } - template - struct Lookup + template + struct Lookup + { + std::optional lookup(const K& name) const { - std::optional lookup(const K& name) const - { - T ret; - if(embedded ? embedded(name, ret) : dict.tryGetValue(name, ret)) - return ret; - else - return std::nullopt; - } - - bool (*embedded)(const K&, T&) = nullptr; - Dictionary dict; - }; + T ret; + if (embedded ? embedded(name, ret) : dict.tryGetValue(name, ret)) + return ret; + else + return std::nullopt; + } + + bool (*embedded)(const K&, T&) = nullptr; + Dictionary dict; + }; - struct OperandKind - { - uint8_t index; - SLANG_COMPONENTWISE_HASHABLE_1; - SLANG_COMPONENTWISE_EQUALITY_1(OperandKind); - }; + struct OperandKind + { + uint8_t index; + SLANG_COMPONENTWISE_HASHABLE_1; + SLANG_COMPONENTWISE_EQUALITY_1(OperandKind); + }; - struct QualifiedEnumName - { - OperandKind kind; - UnownedStringSlice name; - SLANG_COMPONENTWISE_HASHABLE_2; - SLANG_COMPONENTWISE_EQUALITY_2(QualifiedEnumName); - }; + struct QualifiedEnumName + { + OperandKind kind; + UnownedStringSlice name; + SLANG_COMPONENTWISE_HASHABLE_2; + SLANG_COMPONENTWISE_EQUALITY_2(QualifiedEnumName); + }; - struct QualifiedEnumValue - { - OperandKind kind; - SpvWord value; - SLANG_COMPONENTWISE_HASHABLE_2; - SLANG_COMPONENTWISE_EQUALITY_2(QualifiedEnumValue); - }; + struct QualifiedEnumValue + { + OperandKind kind; + SpvWord value; + SLANG_COMPONENTWISE_HASHABLE_2; + SLANG_COMPONENTWISE_EQUALITY_2(QualifiedEnumValue); + }; - struct OpInfo + struct OpInfo + { + enum Class { - enum Class - { - // Unrecognized instructions go in here - Other, - - // Adding to this? Don't forget to update the embedding generator - Miscellaneous, - Debug, - Annotation, - Extension, - ModeSetting, - TypeDeclaration, - ConstantCreation, - Memory, - Function, - Image, - Conversion, - Composite, - Arithmetic, - Bit, - Relational_and_Logical, - Derivative, - ControlFlow, - Atomic, - Primitive, - Barrier, - Group, - DeviceSideEnqueue, - Pipe, - NonUniform, - Reserved, - }; - constexpr static int8_t kNoResultTypeId = -1; - constexpr static int8_t kNoResultId = -1; - - Class class_; - // -1 or 0 - int8_t resultTypeIndex = kNoResultTypeId; - // -1 or 0 or 1 - int8_t resultIdIndex = kNoResultId; - // The range of valid operand counts for this instruction, - // including any result type and id. Multi-word operands count as a - // single operand. - uint16_t minOperandCount; - uint16_t maxOperandCount; - // when looking up an operand type, clamp to this number-1 to - // account for variable length operands at the end - uint16_t numOperandTypes; - const OperandKind* operandTypes; + // Unrecognized instructions go in here + Other, + + // Adding to this? Don't forget to update the embedding generator + Miscellaneous, + Debug, + Annotation, + Extension, + ModeSetting, + TypeDeclaration, + ConstantCreation, + Memory, + Function, + Image, + Conversion, + Composite, + Arithmetic, + Bit, + Relational_and_Logical, + Derivative, + ControlFlow, + Atomic, + Primitive, + Barrier, + Group, + DeviceSideEnqueue, + Pipe, + NonUniform, + Reserved, }; - - // - // Our tables: - // - - // Instruction name to opcode - Lookup opcodes; - // Capability name to value - Lookup capabilities; - // String-qualified enum name (one with the type prefix) to value - Lookup allEnumsWithTypePrefix; - // kind * enum name to value - Lookup allEnums; - // kine * enum value to unqualified name - Lookup allEnumNames; - // Any other information on instructions - Lookup opInfos; - // Opcode to instruction name - Lookup opNames; - // Operand kind string to numeric id - Lookup operandKinds; - // Operand kind id to string - Lookup operandKindNames; - // Operand kind to the "un-id" version of itself, for example IdMemorySemantics to MemorySemantics - Lookup operandKindUnderneathIds; - - private: - - // If this is loaded from JSON, we keep the strings around instead of - // copying them as dictionary keys - StringSlicePool strings = StringSlicePool(StringSlicePool::Style::Empty); - List operandTypesStorage; + constexpr static int8_t kNoResultTypeId = -1; + constexpr static int8_t kNoResultId = -1; + + Class class_; + // -1 or 0 + int8_t resultTypeIndex = kNoResultTypeId; + // -1 or 0 or 1 + int8_t resultIdIndex = kNoResultId; + // The range of valid operand counts for this instruction, + // including any result type and id. Multi-word operands count as a + // single operand. + uint16_t minOperandCount; + uint16_t maxOperandCount; + // when looking up an operand type, clamp to this number-1 to + // account for variable length operands at the end + uint16_t numOperandTypes; + const OperandKind* operandTypes; }; -} + + // + // Our tables: + // + + // Instruction name to opcode + Lookup opcodes; + // Capability name to value + Lookup capabilities; + // String-qualified enum name (one with the type prefix) to value + Lookup allEnumsWithTypePrefix; + // kind * enum name to value + Lookup allEnums; + // kine * enum value to unqualified name + Lookup allEnumNames; + // Any other information on instructions + Lookup opInfos; + // Opcode to instruction name + Lookup opNames; + // Operand kind string to numeric id + Lookup operandKinds; + // Operand kind id to string + Lookup operandKindNames; + // Operand kind to the "un-id" version of itself, for example IdMemorySemantics to + // MemorySemantics + Lookup operandKindUnderneathIds; + +private: + // If this is loaded from JSON, we keep the strings around instead of + // copying them as dictionary keys + StringSlicePool strings = StringSlicePool(StringSlicePool::Style::Empty); + List operandTypesStorage; +}; +} // namespace Slang diff --git a/source/compiler-core/slang-test-server-protocol.cpp b/source/compiler-core/slang-test-server-protocol.cpp index 2a3bb3a3b..248c6a07a 100644 --- a/source/compiler-core/slang-test-server-protocol.cpp +++ b/source/compiler-core/slang-test-server-protocol.cpp @@ -1,6 +1,7 @@ #include "slang-test-server-protocol.h" -namespace TestServerProtocol { +namespace TestServerProtocol +{ static const StructRttiInfo _makeExecuteUnitTestArgsRtti() { @@ -12,8 +13,9 @@ static const StructRttiInfo _makeExecuteUnitTestArgsRtti() builder.addField("enabledApis", &obj.enabledApis); return builder.make(); } -/* static */const UnownedStringSlice ExecuteUnitTestArgs::g_methodName = UnownedStringSlice::fromLiteral("unitTest"); -/* static */const StructRttiInfo ExecuteUnitTestArgs::g_rttiInfo = _makeExecuteUnitTestArgsRtti(); +/* static */ const UnownedStringSlice ExecuteUnitTestArgs::g_methodName = + UnownedStringSlice::fromLiteral("unitTest"); +/* static */ const StructRttiInfo ExecuteUnitTestArgs::g_rttiInfo = _makeExecuteUnitTestArgsRtti(); static const StructRttiInfo _makeExecuteToolTestArgsRtti() { @@ -23,8 +25,9 @@ static const StructRttiInfo _makeExecuteToolTestArgsRtti() builder.addField("args", &obj.args); return builder.make(); } -/* static */const StructRttiInfo ExecuteToolTestArgs::g_rttiInfo = _makeExecuteToolTestArgsRtti(); -/* static */const UnownedStringSlice ExecuteToolTestArgs::g_methodName = UnownedStringSlice::fromLiteral("tool"); +/* static */ const StructRttiInfo ExecuteToolTestArgs::g_rttiInfo = _makeExecuteToolTestArgsRtti(); +/* static */ const UnownedStringSlice ExecuteToolTestArgs::g_methodName = + UnownedStringSlice::fromLiteral("tool"); static const StructRttiInfo _makeExecutionResultRtti() { @@ -36,8 +39,9 @@ static const StructRttiInfo _makeExecutionResultRtti() builder.addField("returnCode", &obj.returnCode); return builder.make(); } -/* static */const StructRttiInfo ExecutionResult::g_rttiInfo = _makeExecutionResultRtti(); +/* static */ const StructRttiInfo ExecutionResult::g_rttiInfo = _makeExecutionResultRtti(); -/* static */const UnownedStringSlice QuitArgs::g_methodName = UnownedStringSlice::fromLiteral("quit"); +/* static */ const UnownedStringSlice QuitArgs::g_methodName = + UnownedStringSlice::fromLiteral("quit"); } // namespace TestServerProtocol diff --git a/source/compiler-core/slang-test-server-protocol.h b/source/compiler-core/slang-test-server-protocol.h index b74a1a872..a15e19701 100644 --- a/source/compiler-core/slang-test-server-protocol.h +++ b/source/compiler-core/slang-test-server-protocol.h @@ -1,14 +1,14 @@ #ifndef SLANG_COMPILER_CORE_TEST_PROTOCOL_H #define SLANG_COMPILER_CORE_TEST_PROTOCOL_H -#include "slang.h" +#include "../core/slang-rtti-info.h" #include "slang-com-helper.h" #include "slang-com-ptr.h" - -#include "../core/slang-rtti-info.h" #include "slang-json-value.h" +#include "slang.h" -namespace TestServerProtocol { +namespace TestServerProtocol +{ using namespace Slang; @@ -24,8 +24,9 @@ struct ExecuteUnitTestArgs struct ExecuteToolTestArgs { - String toolName; ///< The name of the tool (will be a shared library typically - like render-test). Doesn't need -tool suffix. - List args; ///< Arguments passed to the tool during exectution + String toolName; ///< The name of the tool (will be a shared library typically - like + ///< render-test). Doesn't need -tool suffix. + List args; ///< Arguments passed to the tool during exectution static const UnownedStringSlice g_methodName; static const StructRttiInfo g_rttiInfo; @@ -41,11 +42,11 @@ struct ExecutionResult String stdOut; String stdError; int32_t result = SLANG_OK; - int32_t returnCode = 0; ///< As returned if invoked as command line + int32_t returnCode = 0; ///< As returned if invoked as command line static const StructRttiInfo g_rttiInfo; }; -} // namespace Slang +} // namespace TestServerProtocol #endif // SLANG_COMPILER_CORE_TEST_PROTOCOL_H diff --git a/source/compiler-core/slang-tint-compiler.cpp b/source/compiler-core/slang-tint-compiler.cpp index 6319ecf9f..c656f9ba1 100644 --- a/source/compiler-core/slang-tint-compiler.cpp +++ b/source/compiler-core/slang-tint-compiler.cpp @@ -1,164 +1,152 @@ #include "slang-tint-compiler.h" -#include "slang-artifact-associated-impl.h" - #include "../../external/slang-tint-headers/slang-tint.h" +#include "slang-artifact-associated-impl.h" namespace Slang { - class TintDownstreamCompiler : public DownstreamCompilerBase - { - - public: - - // IDownstreamCompiler - virtual SLANG_NO_THROW SlangResult SLANG_MCALL compile( - const CompileOptions& options, IArtifact** outResult) SLANG_OVERRIDE; - - virtual SLANG_NO_THROW bool SLANG_MCALL canConvert( - const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; +class TintDownstreamCompiler : public DownstreamCompilerBase +{ - virtual SLANG_NO_THROW SlangResult SLANG_MCALL convert( - IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) - SLANG_OVERRIDE; +public: + // IDownstreamCompiler + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + compile(const CompileOptions& options, IArtifact** outResult) SLANG_OVERRIDE; - virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE - { - return false; - } + virtual SLANG_NO_THROW bool SLANG_MCALL + canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE; - virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString( - slang::IBlob** outVersionString) SLANG_OVERRIDE; + virtual SLANG_NO_THROW SlangResult SLANG_MCALL + convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE; - SlangResult compile(IArtifact *const sourceArtifact, IArtifact** outArtifact); + virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; } - SlangResult init(ISlangSharedLibrary* library); + virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString) + SLANG_OVERRIDE; - protected: + SlangResult compile(IArtifact* const sourceArtifact, IArtifact** outArtifact); - ComPtr m_sharedLibrary; + SlangResult init(ISlangSharedLibrary* library); - private: +protected: + ComPtr m_sharedLibrary; - tint_CompileFunc m_compile; - tint_FreeResultFunc m_freeResult; - }; +private: + tint_CompileFunc m_compile; + tint_FreeResultFunc m_freeResult; +}; - SlangResult TintDownstreamCompiler::init(ISlangSharedLibrary* library) +SlangResult TintDownstreamCompiler::init(ISlangSharedLibrary* library) +{ + tint_CompileFunc compile = (tint_CompileFunc)library->findFuncByName("tint_compile"); + if (compile == nullptr) { - tint_CompileFunc compile = - (tint_CompileFunc)library->findFuncByName("tint_compile"); - if (compile == nullptr) - { - return SLANG_FAIL; - } - - tint_FreeResultFunc freeResult = - (tint_FreeResultFunc)library->findFuncByName("tint_free_result"); - if (freeResult == nullptr) - { - return SLANG_FAIL; - } - - m_sharedLibrary = library; - m_desc = Desc(SLANG_PASS_THROUGH_TINT); - m_compile = compile; - m_freeResult = freeResult; - return SLANG_OK; + return SLANG_FAIL; } - SlangResult TintDownstreamCompilerUtil::locateCompilers( - const String& path, - ISlangSharedLibraryLoader* loader, - DownstreamCompilerSet* set) + tint_FreeResultFunc freeResult = + (tint_FreeResultFunc)library->findFuncByName("tint_free_result"); + if (freeResult == nullptr) { - ComPtr library; - SLANG_RETURN_ON_FAIL(DownstreamCompilerUtil::loadSharedLibrary( - path, loader, nullptr, "slang-tint", library)); - SLANG_ASSERT(library); - - ComPtr compiler = ComPtr( - new TintDownstreamCompiler()); - SLANG_RETURN_ON_FAIL(static_cast( - compiler.get())->init(library)); - - set->addCompiler(compiler); - return SLANG_OK; + return SLANG_FAIL; } - SlangResult TintDownstreamCompiler::compile( - const CompileOptions& options, IArtifact** outArtifact) - { - IArtifact * sourceArtifact = options.sourceArtifacts[0]; - return compile(sourceArtifact, outArtifact); - } + m_sharedLibrary = library; + m_desc = Desc(SLANG_PASS_THROUGH_TINT); + m_compile = compile; + m_freeResult = freeResult; + return SLANG_OK; +} - SlangResult TintDownstreamCompiler::compile( - IArtifact *const sourceArtifact, IArtifact** outArtifact) - { - tint_CompileRequest req = {}; - - if (sourceArtifact == nullptr) - return SLANG_FAIL; - - ComPtr sourceBlob; - SLANG_RETURN_FALSE_ON_FAIL(sourceArtifact->loadBlob( - ArtifactKeep::Yes, sourceBlob.writeRef())); - - String wgslCode( - (char*)sourceBlob->getBufferPointer(), - (char*)sourceBlob->getBufferPointer() + sourceBlob->getBufferSize()); - req.wgslCode = wgslCode.begin(); - req.wgslCodeLength = wgslCode.getLength(); - - tint_CompileResult result = {}; - SLANG_DEFER(m_freeResult(&result)); - bool compileSucceeded = m_compile(&req, &result) == 0; - - ComPtr spirvBlob = RawBlob::create(result.buffer, result.bufferSize); - result.buffer = nullptr; - - ComPtr resultArtifact = ArtifactUtil::createArtifactForCompileTarget( - SlangCompileTarget::SLANG_WGSL_SPIRV); - auto diagnostics = ArtifactDiagnostics::create(); - diagnostics->setResult(compileSucceeded ? SLANG_OK : SLANG_FAIL); - ArtifactUtil::addAssociated(resultArtifact, diagnostics); - if (compileSucceeded) - { - resultArtifact->addRepresentationUnknown(spirvBlob); - } - else - { - diagnostics->setRaw(CharSlice(result.error)); - diagnostics->requireErrorDiagnostic(); - } - - *outArtifact = resultArtifact.detach(); - return SLANG_OK; - } +SlangResult TintDownstreamCompilerUtil::locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set) +{ + ComPtr library; + SLANG_RETURN_ON_FAIL( + DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, "slang-tint", library)); + SLANG_ASSERT(library); - bool TintDownstreamCompiler::canConvert( - const ArtifactDesc& from, const ArtifactDesc& to) + ComPtr compiler = + ComPtr(new TintDownstreamCompiler()); + SLANG_RETURN_ON_FAIL(static_cast(compiler.get())->init(library)); + + set->addCompiler(compiler); + return SLANG_OK; +} + +SlangResult TintDownstreamCompiler::compile(const CompileOptions& options, IArtifact** outArtifact) +{ + IArtifact* sourceArtifact = options.sourceArtifacts[0]; + return compile(sourceArtifact, outArtifact); +} + +SlangResult TintDownstreamCompiler::compile( + IArtifact* const sourceArtifact, + IArtifact** outArtifact) +{ + tint_CompileRequest req = {}; + + if (sourceArtifact == nullptr) + return SLANG_FAIL; + + ComPtr sourceBlob; + SLANG_RETURN_FALSE_ON_FAIL(sourceArtifact->loadBlob(ArtifactKeep::Yes, sourceBlob.writeRef())); + + String wgslCode( + (char*)sourceBlob->getBufferPointer(), + (char*)sourceBlob->getBufferPointer() + sourceBlob->getBufferSize()); + req.wgslCode = wgslCode.begin(); + req.wgslCodeLength = wgslCode.getLength(); + + tint_CompileResult result = {}; + SLANG_DEFER(m_freeResult(&result)); + bool compileSucceeded = m_compile(&req, &result) == 0; + + ComPtr spirvBlob = RawBlob::create(result.buffer, result.bufferSize); + result.buffer = nullptr; + + ComPtr resultArtifact = + ArtifactUtil::createArtifactForCompileTarget(SlangCompileTarget::SLANG_WGSL_SPIRV); + auto diagnostics = ArtifactDiagnostics::create(); + diagnostics->setResult(compileSucceeded ? SLANG_OK : SLANG_FAIL); + ArtifactUtil::addAssociated(resultArtifact, diagnostics); + if (compileSucceeded) { - return (from.payload == ArtifactPayload::WGSL) && - (to.payload == ArtifactPayload::SPIRV); + resultArtifact->addRepresentationUnknown(spirvBlob); } - - SlangResult TintDownstreamCompiler::convert( - IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) + else { - if (!canConvert(from->getDesc(), to)) - return SLANG_FAIL; - return compile(from, outArtifact); + diagnostics->setRaw(CharSlice(result.error)); + diagnostics->requireErrorDiagnostic(); } - SlangResult TintDownstreamCompiler::getVersionString( - slang::IBlob** /* outVersionString */) - { - // We just use Tint at whatever version is in our Dawn fork, so nobody should - // depend on the particular version at the moment. + *outArtifact = resultArtifact.detach(); + return SLANG_OK; +} + +bool TintDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactDesc& to) +{ + return (from.payload == ArtifactPayload::WGSL) && (to.payload == ArtifactPayload::SPIRV); +} + +SlangResult TintDownstreamCompiler::convert( + IArtifact* from, + const ArtifactDesc& to, + IArtifact** outArtifact) +{ + if (!canConvert(from->getDesc(), to)) return SLANG_FAIL; - } + return compile(from, outArtifact); +} +SlangResult TintDownstreamCompiler::getVersionString(slang::IBlob** /* outVersionString */) +{ + // We just use Tint at whatever version is in our Dawn fork, so nobody should + // depend on the particular version at the moment. + return SLANG_FAIL; } + +} // namespace Slang diff --git a/source/compiler-core/slang-tint-compiler.h b/source/compiler-core/slang-tint-compiler.h index d5e596d4d..74953c378 100644 --- a/source/compiler-core/slang-tint-compiler.h +++ b/source/compiler-core/slang-tint-compiler.h @@ -1,17 +1,17 @@ #pragma once -#include "slang-downstream-compiler-util.h" #include "../core/slang-platform.h" +#include "slang-downstream-compiler-util.h" namespace Slang { - struct TintDownstreamCompilerUtil - { - static SlangResult locateCompilers( - const String& path, - ISlangSharedLibraryLoader* loader, - DownstreamCompilerSet* set); - }; +struct TintDownstreamCompilerUtil +{ + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); +}; -} +} // namespace Slang diff --git a/source/compiler-core/slang-token-defs.h b/source/compiler-core/slang-token-defs.h index 2a66359fe..fea90b3ee 100644 --- a/source/compiler-core/slang-token-defs.h +++ b/source/compiler-core/slang-token-defs.h @@ -16,80 +16,79 @@ #error Need to define TOKEN(ID, DESC) before including "token-defs.h" #endif -TOKEN(Unknown, "") -TOKEN(EndOfFile, "end of file") -TOKEN(Invalid, "invalid character") -TOKEN(Identifier, "identifier") -TOKEN(IntegerLiteral, "integer literal") -TOKEN(FloatingPointLiteral, "floating-point literal") -TOKEN(StringLiteral, "string literal") -TOKEN(CharLiteral, "character literal") -TOKEN(WhiteSpace, "whitespace") -TOKEN(NewLine, "end of line") -TOKEN(LineComment, "line comment") -TOKEN(BlockComment, "block comment") +TOKEN(Unknown, "") +TOKEN(EndOfFile, "end of file") +TOKEN(Invalid, "invalid character") +TOKEN(Identifier, "identifier") +TOKEN(IntegerLiteral, "integer literal") +TOKEN(FloatingPointLiteral, "floating-point literal") +TOKEN(StringLiteral, "string literal") +TOKEN(CharLiteral, "character literal") +TOKEN(WhiteSpace, "whitespace") +TOKEN(NewLine, "end of line") +TOKEN(LineComment, "line comment") +TOKEN(BlockComment, "block comment") -#define PUNCTUATION(id, text) \ - TOKEN(id, "'" text "'") +#define PUNCTUATION(id, text) TOKEN(id, "'" text "'") -PUNCTUATION(Semicolon, ";") -PUNCTUATION(Comma, ",") -PUNCTUATION(Dot, ".") -PUNCTUATION(DotDot, "..") -PUNCTUATION(Ellipsis, "...") +PUNCTUATION(Semicolon, ";") +PUNCTUATION(Comma, ",") +PUNCTUATION(Dot, ".") +PUNCTUATION(DotDot, "..") +PUNCTUATION(Ellipsis, "...") -PUNCTUATION(LBrace, "{") -PUNCTUATION(RBrace, "}") -PUNCTUATION(LBracket, "[") -PUNCTUATION(RBracket, "]") -PUNCTUATION(LParent, "(") -PUNCTUATION(RParent, ")") +PUNCTUATION(LBrace, "{") +PUNCTUATION(RBrace, "}") +PUNCTUATION(LBracket, "[") +PUNCTUATION(RBracket, "]") +PUNCTUATION(LParent, "(") +PUNCTUATION(RParent, ")") -PUNCTUATION(OpAssign, "=") -PUNCTUATION(OpAdd, "+") -PUNCTUATION(OpSub, "-") -PUNCTUATION(OpMul, "*") -PUNCTUATION(OpDiv, "/") -PUNCTUATION(OpMod, "%") -PUNCTUATION(OpNot, "!") -PUNCTUATION(OpBitNot, "~") -PUNCTUATION(OpLsh, "<<") -PUNCTUATION(OpRsh, ">>") -PUNCTUATION(OpEql, "==") -PUNCTUATION(OpNeq, "!=") -PUNCTUATION(OpGreater, ">") -PUNCTUATION(OpLess, "<") -PUNCTUATION(OpGeq, ">=") -PUNCTUATION(OpLeq, "<=") -PUNCTUATION(OpAnd, "&&") -PUNCTUATION(OpOr, "||") -PUNCTUATION(OpBitAnd, "&") -PUNCTUATION(OpBitOr, "|") -PUNCTUATION(OpBitXor, "^") -PUNCTUATION(OpInc, "++") -PUNCTUATION(OpDec, "--") +PUNCTUATION(OpAssign, "=") +PUNCTUATION(OpAdd, "+") +PUNCTUATION(OpSub, "-") +PUNCTUATION(OpMul, "*") +PUNCTUATION(OpDiv, "/") +PUNCTUATION(OpMod, "%") +PUNCTUATION(OpNot, "!") +PUNCTUATION(OpBitNot, "~") +PUNCTUATION(OpLsh, "<<") +PUNCTUATION(OpRsh, ">>") +PUNCTUATION(OpEql, "==") +PUNCTUATION(OpNeq, "!=") +PUNCTUATION(OpGreater, ">") +PUNCTUATION(OpLess, "<") +PUNCTUATION(OpGeq, ">=") +PUNCTUATION(OpLeq, "<=") +PUNCTUATION(OpAnd, "&&") +PUNCTUATION(OpOr, "||") +PUNCTUATION(OpBitAnd, "&") +PUNCTUATION(OpBitOr, "|") +PUNCTUATION(OpBitXor, "^") +PUNCTUATION(OpInc, "++") +PUNCTUATION(OpDec, "--") -PUNCTUATION(OpAddAssign, "+=") -PUNCTUATION(OpSubAssign, "-=") -PUNCTUATION(OpMulAssign, "*=") -PUNCTUATION(OpDivAssign, "/=") -PUNCTUATION(OpModAssign, "%=") -PUNCTUATION(OpShlAssign, "<<=") -PUNCTUATION(OpShrAssign, ">>=") -PUNCTUATION(OpAndAssign, "&=") -PUNCTUATION(OpOrAssign, "|=") -PUNCTUATION(OpXorAssign, "^=") +PUNCTUATION(OpAddAssign, "+=") +PUNCTUATION(OpSubAssign, "-=") +PUNCTUATION(OpMulAssign, "*=") +PUNCTUATION(OpDivAssign, "/=") +PUNCTUATION(OpModAssign, "%=") +PUNCTUATION(OpShlAssign, "<<=") +PUNCTUATION(OpShrAssign, ">>=") +PUNCTUATION(OpAndAssign, "&=") +PUNCTUATION(OpOrAssign, "|=") +PUNCTUATION(OpXorAssign, "^=") -PUNCTUATION(QuestionMark, "?") -PUNCTUATION(Colon, ":") -PUNCTUATION(RightArrow, "->") -PUNCTUATION(At, "@") -PUNCTUATION(Dollar, "$") -PUNCTUATION(DollarDollar, "$$") -PUNCTUATION(Pound, "#") -PUNCTUATION(PoundPound, "##") +PUNCTUATION(QuestionMark, "?") +PUNCTUATION(Colon, ":") +PUNCTUATION(RightArrow, "->") +PUNCTUATION(At, "@") +PUNCTUATION(Dollar, "$") +PUNCTUATION(DollarDollar, "$$") +PUNCTUATION(Pound, "#") +PUNCTUATION(PoundPound, "##") -PUNCTUATION(Scope, "::") +PUNCTUATION(Scope, "::") PUNCTUATION(CompletionRequest, "#?") diff --git a/source/compiler-core/slang-token.cpp b/source/compiler-core/slang-token.cpp index 576b08d66..5dd64b96a 100644 --- a/source/compiler-core/slang-token.cpp +++ b/source/compiler-core/slang-token.cpp @@ -1,19 +1,19 @@ // slang-token.cpp #include "slang-token.h" -//#include +// #include -namespace Slang { +namespace Slang +{ char const* TokenTypeToString(TokenType type) { - switch( type ) + switch (type) { - default: - SLANG_ASSERT(!"unexpected"); - return ""; + default: SLANG_ASSERT(!"unexpected"); return ""; -#define TOKEN(NAME, DESC) case TokenType::NAME: return DESC; +#define TOKEN(NAME, DESC) \ + case TokenType::NAME: return DESC; #include "slang-token-defs.h" } } diff --git a/source/compiler-core/slang-token.h b/source/compiler-core/slang-token.h index 7feda6824..9978ec5cf 100644 --- a/source/compiler-core/slang-token.h +++ b/source/compiler-core/slang-token.h @@ -3,11 +3,11 @@ #define SLANG_TOKEN_H_INCLUDED #include "../core/slang-basic.h" - -#include "slang-source-loc.h" #include "slang-name.h" +#include "slang-source-loc.h" -namespace Slang { +namespace Slang +{ class Name; @@ -24,22 +24,21 @@ struct TokenFlag { enum Enum : TokenFlags { - AtStartOfLine = 1 << 0, - AfterWhitespace = 1 << 1, - ScrubbingNeeded = 1 << 2, - Name = 1 << 3, ///< Determines if 'name' is set or 'chars' in the charsNameUnion + AtStartOfLine = 1 << 0, + AfterWhitespace = 1 << 1, + ScrubbingNeeded = 1 << 2, + Name = 1 << 3, ///< Determines if 'name' is set or 'chars' in the charsNameUnion }; }; class Token { public: + TokenType type = TokenType::Unknown; + TokenFlags flags = 0; - TokenType type = TokenType::Unknown; - TokenFlags flags = 0; - - SourceLoc loc; - uint32_t charsCount = 0; ///< Amount of characters. Is set if name or not. + SourceLoc loc; + uint32_t charsCount = 0; ///< Amount of characters. Is set if name or not. union CharsNameUnion { @@ -53,7 +52,7 @@ public: Index getContentLength() const { return charsCount; } UnownedStringSlice getContent() const; - /// Set content + /// Set content void setContent(const UnownedStringSlice& content); Name* getName() const; @@ -62,13 +61,10 @@ public: SourceLoc getLoc() const { return loc; } - /// Set the name + /// Set the name SLANG_FORCE_INLINE void setName(Name* inName); - Token() - { - charsNameUnion.chars = nullptr; - } + Token() { charsNameUnion.chars = nullptr; } Token( TokenType inType, @@ -76,18 +72,14 @@ public: SourceLoc inLoc, TokenFlags inFlags = 0) : flags(inFlags) - { - SLANG_ASSERT((inFlags & TokenFlag::Name) == 0); - type = inType; + { + SLANG_ASSERT((inFlags & TokenFlag::Name) == 0); + type = inType; charsNameUnion.chars = inContent.begin(); charsCount = uint32_t(inContent.getLength()); loc = inLoc; - } - Token( - TokenType inType, - Name* name, - SourceLoc inLoc, - TokenFlags inFlags = 0) + } + Token(TokenType inType, Name* name, SourceLoc inLoc, TokenFlags inFlags = 0) { SLANG_ASSERT(name); type = inType; @@ -101,7 +93,8 @@ public: // --------------------------------------------------------------------------- SLANG_FORCE_INLINE UnownedStringSlice Token::getContent() const { - return (flags & TokenFlag::Name) ? charsNameUnion.name->text.getUnownedSlice() : UnownedStringSlice(charsNameUnion.chars, charsCount); + return (flags & TokenFlag::Name) ? charsNameUnion.name->text.getUnownedSlice() + : UnownedStringSlice(charsNameUnion.chars, charsCount); } // --------------------------------------------------------------------------- diff --git a/source/compiler-core/slang-visual-studio-compiler-util.cpp b/source/compiler-core/slang-visual-studio-compiler-util.cpp index df3285608..449b0f973 100644 --- a/source/compiler-core/slang-visual-studio-compiler-util.cpp +++ b/source/compiler-core/slang-visual-studio-compiler-util.cpp @@ -2,35 +2,45 @@ #include "slang-visual-studio-compiler-util.h" #include "../core/slang-common.h" -#include "slang-com-helper.h" -#include "../core/slang-string-util.h" #include "../core/slang-string-slice-pool.h" +#include "../core/slang-string-util.h" +#include "slang-com-helper.h" // if Visual Studio import the visual studio platform specific header #if SLANG_VC -# include "windows/slang-win-visual-studio-util.h" +#include "windows/slang-win-visual-studio-util.h" #endif #include "../core/slang-io.h" - #include "slang-artifact-desc-util.h" #include "slang-artifact-diagnostic-util.h" -#include "slang-artifact-util.h" #include "slang-artifact-representation-impl.h" +#include "slang-artifact-util.h" namespace Slang { -static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts) +static void _addFile( + const String& path, + const ArtifactDesc& desc, + IOSFileArtifactRepresentation* lockFile, + List>& outArtifacts) { - auto fileRep = OSFileArtifactRepresentation::create(IOSFileArtifactRepresentation::Kind::Owned, path.getUnownedSlice(), lockFile); + auto fileRep = OSFileArtifactRepresentation::create( + IOSFileArtifactRepresentation::Kind::Owned, + path.getUnownedSlice(), + lockFile); auto artifact = ArtifactUtil::createArtifact(desc); artifact->addRepresentation(fileRep); outArtifacts.add(artifact); } -/* static */SlangResult VisualStudioCompilerUtil::calcCompileProducts(const CompileOptions& options, ProductFlags flags, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts) +/* static */ SlangResult VisualStudioCompilerUtil::calcCompileProducts( + const CompileOptions& options, + ProductFlags flags, + IOSFileArtifactRepresentation* lockFile, + List>& outArtifacts) { SLANG_ASSERT(options.modulePath.count); @@ -44,35 +54,67 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa { StringBuilder builder; const auto desc = ArtifactDescUtil::makeDescForCompileTarget(options.targetType); - SLANG_RETURN_ON_FAIL(ArtifactDescUtil::calcPathForDesc(desc, modulePath.getUnownedSlice(), builder)); + SLANG_RETURN_ON_FAIL( + ArtifactDescUtil::calcPathForDesc(desc, modulePath.getUnownedSlice(), builder)); _addFile(builder, desc, lockFile, outArtifacts); } if (flags & ProductFlag::Miscellaneous) { - - _addFile(modulePath + ".ilk", ArtifactDesc::make(ArtifactKind::BinaryFormat, ArtifactPayload::Unknown, ArtifactStyle::None), lockFile, outArtifacts); + + _addFile( + modulePath + ".ilk", + ArtifactDesc::make( + ArtifactKind::BinaryFormat, + ArtifactPayload::Unknown, + ArtifactStyle::None), + lockFile, + outArtifacts); if (options.targetType == SLANG_SHADER_SHARED_LIBRARY) { - _addFile(modulePath + ".exp", ArtifactDesc::make(ArtifactKind::BinaryFormat, ArtifactPayload::Unknown, ArtifactStyle::None), lockFile, outArtifacts); - _addFile(modulePath + ".lib", ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::HostCPU, targetDesc), lockFile, outArtifacts); + _addFile( + modulePath + ".exp", + ArtifactDesc::make( + ArtifactKind::BinaryFormat, + ArtifactPayload::Unknown, + ArtifactStyle::None), + lockFile, + outArtifacts); + _addFile( + modulePath + ".lib", + ArtifactDesc::make(ArtifactKind::Library, ArtifactPayload::HostCPU, targetDesc), + lockFile, + outArtifacts); } } if (flags & ProductFlag::Compile) { - _addFile(modulePath + ".obj", ArtifactDesc::make(ArtifactKind::ObjectCode, ArtifactPayload::HostCPU, targetDesc), lockFile, outArtifacts); + _addFile( + modulePath + ".obj", + ArtifactDesc::make(ArtifactKind::ObjectCode, ArtifactPayload::HostCPU, targetDesc), + lockFile, + outArtifacts); } if (flags & ProductFlag::Debug) { // TODO(JS): Could try and determine based on debug information - _addFile(modulePath + ".pdb", ArtifactDesc::make(ArtifactKind::BinaryFormat, ArtifactPayload::PdbDebugInfo, targetDesc), lockFile, outArtifacts); + _addFile( + modulePath + ".pdb", + ArtifactDesc::make( + ArtifactKind::BinaryFormat, + ArtifactPayload::PdbDebugInfo, + targetDesc), + lockFile, + outArtifacts); } return SLANG_OK; } -/* static */SlangResult VisualStudioCompilerUtil::calcArgs(const CompileOptions& options, CommandLine& cmdLine) +/* static */ SlangResult VisualStudioCompilerUtil::calcArgs( + const CompileOptions& options, + CommandLine& cmdLine) { SLANG_ASSERT(options.modulePath.count); @@ -112,17 +154,17 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa switch (options.debugInfoType) { - default: + default: { // Multithreaded statically linked runtime library cmdLine.addArg("/MD"); break; } - case DebugInfoType::None: + case DebugInfoType::None: { break; } - case DebugInfoType::Maximal: + case DebugInfoType::Maximal: { // Multithreaded statically linked *debug* runtime library cmdLine.addArg("/MDd"); @@ -140,44 +182,46 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa switch (options.optimizationLevel) { - case OptimizationLevel::None: + case OptimizationLevel::None: { // No optimization - cmdLine.addArg("/Od"); + cmdLine.addArg("/Od"); break; } - case OptimizationLevel::Default: + case OptimizationLevel::Default: { break; } - case OptimizationLevel::High: + case OptimizationLevel::High: { cmdLine.addArg("/O2"); break; } - case OptimizationLevel::Maximal: + case OptimizationLevel::Maximal: { cmdLine.addArg("/Ox"); break; } - default: break; + default: break; } switch (options.floatingPointMode) { - case FloatingPointMode::Default: break; - case FloatingPointMode::Precise: + case FloatingPointMode::Default: break; + case FloatingPointMode::Precise: { // precise is default behavior, VS also has 'strict' // - // ```/fp:strict has behavior similar to /fp:precise, that is, the compiler preserves the source ordering and rounding properties of floating-point code when - // it generates and optimizes object code for the target machine, and observes the standard when handling special values. In addition, the program may safely - // access or modify the floating-point environment at runtime.``` + // ```/fp:strict has behavior similar to /fp:precise, that is, the compiler preserves + // the source ordering and rounding properties of floating-point code when it generates + // and optimizes object code for the target machine, and observes the standard when + // handling special values. In addition, the program may safely access or modify the + // floating-point environment at runtime.``` cmdLine.addArg("/fp:precise"); break; } - case FloatingPointMode::Fast: + case FloatingPointMode::Fast: { cmdLine.addArg("/fp:fast"); break; @@ -188,8 +232,8 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa switch (options.targetType) { - case SLANG_SHADER_SHARED_LIBRARY: - case SLANG_HOST_SHARED_LIBRARY: + case SLANG_SHADER_SHARED_LIBRARY: + case SLANG_HOST_SHARED_LIBRARY: { // Create dynamic link library if (options.debugInfoType == DebugInfoType::None) @@ -204,12 +248,12 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa cmdLine.addPrefixPathArg("/Fe", modulePath, ".dll"); break; } - case SLANG_HOST_EXECUTABLE: + case SLANG_HOST_EXECUTABLE: { cmdLine.addPrefixPathArg("/Fe", modulePath, ".exe"); break; } - default: break; + default: break; } // Object file specify it's location - needed if we are out @@ -244,12 +288,12 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa { ComPtr fileRep; - // TODO(JS): + // TODO(JS): // Do we want to keep the file on the file system? It's probably reasonable to do so. SLANG_RETURN_ON_FAIL(sourceArtifact->requireFile(ArtifactKeep::Yes, fileRep.writeRef())); cmdLine.addArg(fileRep->getPath()); } - + // Link options (parameters past /link go to linker) cmdLine.addArg("/link"); @@ -288,7 +332,9 @@ static void _addFile(const String& path, const ArtifactDesc& desc, IOSFileArtifa return SLANG_OK; } -static SlangResult _parseSeverity(const UnownedStringSlice& in, ArtifactDiagnostic::Severity& outSeverity) +static SlangResult _parseSeverity( + const UnownedStringSlice& in, + ArtifactDiagnostic::Severity& outSeverity) { typedef ArtifactDiagnostic::Severity Severity; @@ -311,7 +357,10 @@ static SlangResult _parseSeverity(const UnownedStringSlice& in, ArtifactDiagnost return SLANG_OK; } -static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const UnownedStringSlice& line, ArtifactDiagnostic& outDiagnostic) +static SlangResult _parseVisualStudioLine( + SliceAllocator& allocator, + const UnownedStringSlice& line, + ArtifactDiagnostic& outDiagnostic) { typedef IArtifactDiagnostics::Diagnostic Diagnostic; @@ -328,8 +377,8 @@ static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const Unown outDiagnostic.stage = ArtifactDiagnostic::Stage::Compile; - const char*const start = line.begin(); - const char*const end = line.end(); + const char* const start = line.begin(); + const char* const end = line.end(); UnownedStringSlice postPath; // Handle the path and line no @@ -409,7 +458,8 @@ static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const Unown return SLANG_FAIL; } - const UnownedStringSlice errorSection = UnownedStringSlice(postPath.begin(), postPath.begin() + errorColonIndex); + const UnownedStringSlice errorSection = + UnownedStringSlice(postPath.begin(), postPath.begin() + errorColonIndex); Index errorCodeIndex = errorSection.lastIndexOf(' '); if (errorCodeIndex < 0) { @@ -417,17 +467,20 @@ static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const Unown } // Extract the code - outDiagnostic.code = allocator.allocate(errorSection.begin() + errorCodeIndex + 1, errorSection.end()); + outDiagnostic.code = + allocator.allocate(errorSection.begin() + errorCodeIndex + 1, errorSection.end()); if (asStringSlice(outDiagnostic.code).startsWith(UnownedStringSlice::fromLiteral("LNK"))) { outDiagnostic.stage = Diagnostic::Stage::Link; } // Extract the bit before the code - SLANG_RETURN_ON_FAIL(_parseSeverity(UnownedStringSlice(errorSection.begin(), errorSection.begin() + errorCodeIndex).trim(), outDiagnostic.severity)); + SLANG_RETURN_ON_FAIL(_parseSeverity( + UnownedStringSlice(errorSection.begin(), errorSection.begin() + errorCodeIndex).trim(), + outDiagnostic.severity)); // Link codes start with LNK prefix - postError = UnownedStringSlice(postPath.begin() + errorColonIndex + 1, end); + postError = UnownedStringSlice(postPath.begin() + errorColonIndex + 1, end); } outDiagnostic.text = allocator.allocate(postError); @@ -435,7 +488,9 @@ static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const Unown return SLANG_OK; } -/* static */SlangResult VisualStudioCompilerUtil::parseOutput(const ExecuteResult& exeRes, IArtifactDiagnostics* diagnostics) +/* static */ SlangResult VisualStudioCompilerUtil::parseOutput( + const ExecuteResult& exeRes, + IArtifactDiagnostics* diagnostics) { diagnostics->reset(); @@ -466,7 +521,7 @@ static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const Unown return SLANG_OK; } -/* static */SlangResult VisualStudioCompilerUtil::locateCompilers( +/* static */ SlangResult VisualStudioCompilerUtil::locateCompilers( const String& path, ISlangSharedLibraryLoader* loader, [[maybe_unused]] DownstreamCompilerSet* set) @@ -484,4 +539,4 @@ static SlangResult _parseVisualStudioLine(SliceAllocator& allocator, const Unown return SLANG_OK; } -} +} // namespace Slang diff --git a/source/compiler-core/slang-visual-studio-compiler-util.h b/source/compiler-core/slang-visual-studio-compiler-util.h index fa1fb7c69..77227ce97 100644 --- a/source/compiler-core/slang-visual-studio-compiler-util.h +++ b/source/compiler-core/slang-visual-studio-compiler-util.h @@ -9,14 +9,21 @@ namespace Slang struct VisualStudioCompilerUtil : public DownstreamCompilerUtilBase { - /// Calculate Visual Studio family compilers cmdLine arguments from options + /// Calculate Visual Studio family compilers cmdLine arguments from options static SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine); - /// Parse Visual Studio exeRes into CPPCompiler::Output + /// Parse Visual Studio exeRes into CPPCompiler::Output static SlangResult parseOutput(const ExecuteResult& exeRes, IArtifactDiagnostics* outOutput); - static SlangResult calcCompileProducts(const CompileOptions& options, ProductFlags flags, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts); + static SlangResult calcCompileProducts( + const CompileOptions& options, + ProductFlags flags, + IOSFileArtifactRepresentation* lockFile, + List>& outArtifacts); - static SlangResult locateCompilers(const String& path, ISlangSharedLibraryLoader* loader, DownstreamCompilerSet* set); + static SlangResult locateCompilers( + const String& path, + ISlangSharedLibraryLoader* loader, + DownstreamCompilerSet* set); }; class VisualStudioDownstreamCompiler : public CommandLineDownstreamCompiler @@ -26,14 +33,32 @@ public: typedef VisualStudioCompilerUtil Util; // CommandLineDownstreamCompiler impl - just forwards to the Util - virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) SLANG_OVERRIDE { return Util::calcArgs(options, cmdLine); } - virtual SlangResult parseOutput(const ExecuteResult& exeResult, IArtifactDiagnostics* diagnostics) SLANG_OVERRIDE { return Util::parseOutput(exeResult, diagnostics); } - virtual SlangResult calcCompileProducts(const CompileOptions& options, DownstreamProductFlags productFlags, IOSFileArtifactRepresentation* lockFile, List>& outArtifacts) SLANG_OVERRIDE { return Util::calcCompileProducts(options, productFlags, lockFile, outArtifacts); } + virtual SlangResult calcArgs(const CompileOptions& options, CommandLine& cmdLine) SLANG_OVERRIDE + { + return Util::calcArgs(options, cmdLine); + } + virtual SlangResult parseOutput( + const ExecuteResult& exeResult, + IArtifactDiagnostics* diagnostics) SLANG_OVERRIDE + { + return Util::parseOutput(exeResult, diagnostics); + } + virtual SlangResult calcCompileProducts( + const CompileOptions& options, + DownstreamProductFlags productFlags, + IOSFileArtifactRepresentation* lockFile, + List>& outArtifacts) SLANG_OVERRIDE + { + return Util::calcCompileProducts(options, productFlags, lockFile, outArtifacts); + } - VisualStudioDownstreamCompiler(const Desc& desc):Super(desc) {} + VisualStudioDownstreamCompiler(const Desc& desc) + : Super(desc) + { + } }; -} +} // namespace Slang #endif diff --git a/source/compiler-core/windows/slang-win-visual-studio-util.cpp b/source/compiler-core/windows/slang-win-visual-studio-util.cpp index cb784b426..8496bb3fd 100644 --- a/source/compiler-core/windows/slang-win-visual-studio-util.cpp +++ b/source/compiler-core/windows/slang-win-visual-studio-util.cpp @@ -3,15 +3,13 @@ #include "../../core/slang-common.h" #include "../../core/slang-process-util.h" #include "../../core/slang-string-util.h" - #include "../slang-json-parser.h" #include "../slang-json-value.h" - #include "../slang-visual-studio-compiler-util.h" #ifdef _WIN32 -# include -# include +#include +#include #pragma comment(lib, "advapi32") #pragma comment(lib, "Shell32") #endif @@ -19,33 +17,35 @@ // The method used to invoke VS was originally inspired by some ideas in // https://github.com/RuntimeCompiledCPlusPlus/RuntimeCompiledCPlusPlus/ -namespace Slang { +namespace Slang +{ // Information on VS versioning can be found here // https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering -namespace { // anonymous +namespace +{ // anonymous struct RegistryInfo { - const char* regName; ///< The name of the entry in the registry - const char* pathFix; ///< With the value from the registry how to fix the path + const char* regName; ///< The name of the entry in the registry + const char* pathFix; ///< With the value from the registry how to fix the path }; struct VersionInfo { - SemanticVersion version; ///< The version - const char* name; ///< The name of the registry key + SemanticVersion version; ///< The version + const char* name; ///< The name of the registry key }; -} // anonymous +} // namespace static SlangResult _readRegistryKey(const char* path, const char* keyName, String& outString) { // https://docs.microsoft.com/en-us/windows/desktop/api/winreg/nf-winreg-regopenkeyexa - HKEY key; - LONG ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, path, 0, KEY_READ | KEY_WOW64_32KEY, &key); + HKEY key; + LONG ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, path, 0, KEY_READ | KEY_WOW64_32KEY, &key); if (ret != ERROR_SUCCESS) { return SLANG_FAIL; @@ -77,8 +77,8 @@ static DownstreamCompilerMatchVersion _makeVersion(int main) return version; } -static DownstreamCompilerMatchVersion _makeVersion(int main, int dot) -{ +static DownstreamCompilerMatchVersion _makeVersion(int main, int dot) +{ DownstreamCompilerMatchVersion version; version.type = SLANG_PASS_THROUGH_VISUAL_STUDIO; version.matchVersion.set(main, dot); @@ -94,8 +94,7 @@ VersionInfo _makeVersionInfo(const char* name, int high, int dot = 0) } // https://en.wikipedia.org/wiki/Microsoft_Visual_Studio -static const VersionInfo s_versionInfos[] = -{ +static const VersionInfo s_versionInfos[] = { _makeVersionInfo("VS 2005", 8), _makeVersionInfo("VS 2008", 9), _makeVersionInfo("VS 2010", 10), @@ -107,15 +106,14 @@ static const VersionInfo s_versionInfos[] = _makeVersionInfo("VS 2022", 17), }; -// When trying to figure out how this stuff works by running regedit - care is needed, -// because what regedit displays varies on which version of regedit is used. -// In order to use the registry paths used here it's necessary to use Start/Run with +// When trying to figure out how this stuff works by running regedit - care is needed, +// because what regedit displays varies on which version of regedit is used. +// In order to use the registry paths used here it's necessary to use Start/Run with // %systemroot%\syswow64\regedit to view 32 bit keys -static const RegistryInfo s_regInfos[] = -{ - {"SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7", "" }, - {"SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7", "VC\\Auxiliary\\Build\\" }, +static const RegistryInfo s_regInfos[] = { + {"SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7", ""}, + {"SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7", "VC\\Auxiliary\\Build\\"}, }; static bool _canUseVSWhere(SemanticVersion version) @@ -149,7 +147,7 @@ static SlangResult _parseVersion(UnownedStringSlice versionString, SemanticVersi } -/* static */DownstreamCompilerMatchVersion WinVisualStudioUtil::getCompiledVersion() +/* static */ DownstreamCompilerMatchVersion WinVisualStudioUtil::getCompiledVersion() { // Get the version of visual studio used to compile this source // Not const, because otherwise we get an warning/error about constant expression... @@ -157,12 +155,12 @@ static SlangResult _parseVersion(UnownedStringSlice versionString, SemanticVersi switch (version) { - case 1400: return _makeVersion(8); - case 1500: return _makeVersion(9); - case 1600: return _makeVersion(10); - case 1700: return _makeVersion(11); - case 1800: return _makeVersion(12); - default: break; + case 1400: return _makeVersion(8); + case 1500: return _makeVersion(9); + case 1600: return _makeVersion(10); + case 1700: return _makeVersion(11); + case 1800: return _makeVersion(12); + default: break; } // Seems like versions go in runs of 10 at this point @@ -176,58 +174,65 @@ static SlangResult _parseVersion(UnownedStringSlice versionString, SemanticVersi { switch (version) { - case 1910: return _makeVersion(15, 0); - case 1911: return _makeVersion(15, 3); - case 1912: return _makeVersion(15, 5); - case 1913: return _makeVersion(15, 6); - case 1914: return _makeVersion(15, 7); - case 1915: return _makeVersion(15, 8); - case 1916: return _makeVersion(15, 9); - default: return _makeVersion(15); + case 1910: return _makeVersion(15, 0); + case 1911: return _makeVersion(15, 3); + case 1912: return _makeVersion(15, 5); + case 1913: return _makeVersion(15, 6); + case 1914: return _makeVersion(15, 7); + case 1915: return _makeVersion(15, 8); + case 1916: return _makeVersion(15, 9); + default: return _makeVersion(15); } } else if (version >= 1920 && version < 1930) { switch (version) { - case 1920: return _makeVersion(16, 0); - case 1921: return _makeVersion(16, 1); - case 1922: return _makeVersion(16, 2); - case 1923: return _makeVersion(16, 3); - case 1924: return _makeVersion(16, 4); - case 1925: return _makeVersion(16, 5); - case 1926: return _makeVersion(16, 6); - case 1927: return _makeVersion(16, 7); - case 1928: return _makeVersion(16, 9); - case 1929: return _makeVersion(16, 11); - default: return _makeVersion(16); + case 1920: return _makeVersion(16, 0); + case 1921: return _makeVersion(16, 1); + case 1922: return _makeVersion(16, 2); + case 1923: return _makeVersion(16, 3); + case 1924: return _makeVersion(16, 4); + case 1925: return _makeVersion(16, 5); + case 1926: return _makeVersion(16, 6); + case 1927: return _makeVersion(16, 7); + case 1928: return _makeVersion(16, 9); + case 1929: return _makeVersion(16, 11); + default: return _makeVersion(16); } } else if (version >= 1930 && version < 1940) { switch (version) { - case 1930: return _makeVersion(17, 0); - case 1931: return _makeVersion(17, 1); - case 1932: return _makeVersion(17, 2); - default: return _makeVersion(17); + case 1930: return _makeVersion(17, 0); + case 1931: return _makeVersion(17, 1); + case 1932: return _makeVersion(17, 2); + default: return _makeVersion(17); } } else if (version >= 1940) { // Its an unknown newer version - return DownstreamCompilerMatchVersion(SLANG_PASS_THROUGH_VISUAL_STUDIO, MatchSemanticVersion::makeFuture()); + return DownstreamCompilerMatchVersion( + SLANG_PASS_THROUGH_VISUAL_STUDIO, + MatchSemanticVersion::makeFuture()); } // Unknown version return DownstreamCompilerMatchVersion(SLANG_PASS_THROUGH_VISUAL_STUDIO, MatchSemanticVersion()); } -static SlangResult _parseJson(const String& contents, DiagnosticSink* sink, JSONContainer* container, JSONValue& outRoot) +static SlangResult _parseJson( + const String& contents, + DiagnosticSink* sink, + JSONContainer* container, + JSONValue& outRoot) { auto sourceManager = sink->getSourceManager(); - SourceFile* sourceFile = sourceManager->createSourceFileWithString(PathInfo::makeUnknown(), contents); + SourceFile* sourceFile = + sourceManager->createSourceFileWithString(PathInfo::makeUnknown(), contents); SourceView* sourceView = sourceManager->createSourceView(sourceFile, nullptr, SourceLoc()); JSONLexer lexer; @@ -246,10 +251,13 @@ static void _orderVersions(List& ioVersions) { typedef WinVisualStudioUtil::VersionPath VersionPath; // Put into increasing version order, from oldest to newest - ioVersions.sort([&](const VersionPath& a, const VersionPath& b) -> bool { return a.version < b.version; }); + ioVersions.sort( + [&](const VersionPath& a, const VersionPath& b) -> bool { return a.version < b.version; }); } -static SlangResult _findVersionsWithVSWhere(const VersionInfo* versionInfo, List& outVersions) +static SlangResult _findVersionsWithVSWhere( + const VersionInfo* versionInfo, + List& outVersions) { typedef WinVisualStudioUtil::VersionPath VersionPath; @@ -269,12 +277,14 @@ static SlangResult _findVersionsWithVSWhere(const VersionInfo* versionInfo, List // Using -? we can find out vswhere options. - // Previous args - works but returns multiple versions, without listing what version is associated with which path - // or the order. - //String args[] = { "-version", versionName, "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", ""-property", "installationPath" }; + // Previous args - works but returns multiple versions, without listing what version is + // associated with which path or the order. + // String args[] = { "-version", versionName, "-requires", + // "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", ""-property", "installationPath" }; - // Use JSON parsing, we can verify the versions for a path, otherwise multiple versions are returned - // not just the version specified. The ordering isn't defined (and -sort doesn't appear to work) + // Use JSON parsing, we can verify the versions for a path, otherwise multiple versions are + // returned not just the version specified. The ordering isn't defined (and -sort doesn't appear + // to work) SemanticVersion requiredVersion; if (versionInfo) @@ -288,9 +298,14 @@ static SlangResult _findVersionsWithVSWhere(const VersionInfo* versionInfo, List // Add other args { - // TODO(JS): + // TODO(JS): // For arm targets will probably need something different for tooling - String args[] = { "-format", "json", "-utf8", "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64" }; + String args[] = { + "-format", + "json", + "-utf8", + "-requires", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64"}; cmd.addArgs(args, SLANG_COUNT_OF(args)); } @@ -316,12 +331,13 @@ static SlangResult _findVersionsWithVSWhere(const VersionInfo* versionInfo, List auto arr = container->getArray(jsonRoot); const auto pathKey = container->getKey(UnownedStringSlice::fromLiteral("installationPath")); - const auto versionKey = container->getKey(UnownedStringSlice::fromLiteral("installationVersion")); + const auto versionKey = + container->getKey(UnownedStringSlice::fromLiteral("installationVersion")); // Find all the versions, that match for (auto elem : arr) { - // Get the path and the name + // Get the path and the name if (elem.getKind() != JSONValue::Kind::Object) { continue; @@ -389,7 +405,7 @@ static SlangResult _findVersionsWithRegistery(List& outVersionPaths) +/* static */ SlangResult WinVisualStudioUtil::find(List& outVersionPaths) { outVersionPaths.clear(); @@ -422,12 +438,15 @@ static SlangResult _findVersionsWithRegistery(List bool { return cur.version.m_major == majorVersion; }); + foundIndex = outVersionPaths.findFirstIndex( + [&](const VersionPath& cur) -> bool + { return cur.version.m_major == majorVersion; }); } else { // See if we can find the exact version - foundIndex = outVersionPaths.findFirstIndex([&](const VersionPath& cur) -> bool { return cur.version == regVersion.version; }); + foundIndex = outVersionPaths.findFirstIndex( + [&](const VersionPath& cur) -> bool { return cur.version == regVersion.version; }); } // If it wasn't found add it. @@ -441,7 +460,7 @@ static SlangResult _findVersionsWithRegistery(List versionPaths; SLANG_RETURN_ON_FAIL(find(versionPaths)); @@ -464,20 +483,23 @@ static SlangResult _findVersionsWithRegistery(List& outVersionPaths); - /// Find and add to the set (if not already there) + /// Find and add to the set (if not already there) static SlangResult find(DownstreamCompilerSet* set); - /// Create the cmdLine to start compiler for specified path + /// Create the cmdLine to start compiler for specified path static void calcExecuteCompilerArgs(const VersionPath& versionPath, CommandLine& outCmdLine); - /// Run visual studio on specified path with the parameters specified on the command line. Output placed in outResult. - static SlangResult executeCompiler(const VersionPath& versionPath, const CommandLine& commandLine, ExecuteResult& outResult); + /// Run visual studio on specified path with the parameters specified on the command line. + /// Output placed in outResult. + static SlangResult executeCompiler( + const VersionPath& versionPath, + const CommandLine& commandLine, + ExecuteResult& outResult); - /// Gets the msc compiler used to compile this version. + /// Gets the msc compiler used to compile this version. static DownstreamCompilerMatchVersion getCompiledVersion(); }; } // namespace Slang -#endif +#endif diff --git a/source/core/slang-allocator.h b/source/core/slang-allocator.h index 8942f993b..03cfabe40 100644 --- a/source/core/slang-allocator.h +++ b/source/core/slang-allocator.h @@ -5,89 +5,77 @@ #include #ifdef _MSC_VER -# include +#include #endif #include namespace Slang { - inline void* alignedAllocate(size_t size, size_t alignment) - { +inline void* alignedAllocate(size_t size, size_t alignment) +{ #ifdef _MSC_VER - return _aligned_malloc(size, alignment); + return _aligned_malloc(size, alignment); #elif defined(__CYGWIN__) - return aligned_alloc(alignment, size); + return aligned_alloc(alignment, size); #else - void* rs = nullptr; - int succ = posix_memalign(&rs, alignment, size); - return (succ == 0) ? rs : nullptr; + void* rs = nullptr; + int succ = posix_memalign(&rs, alignment, size); + return (succ == 0) ? rs : nullptr; #endif - } +} - inline void alignedDeallocate(void* ptr) - { +inline void alignedDeallocate(void* ptr) +{ #ifdef _MSC_VER - _aligned_free(ptr); + _aligned_free(ptr); #else - free(ptr); + free(ptr); #endif - } +} - class StandardAllocator - { - public: - // not really called - void* allocate(size_t size) - { - return ::malloc(size); - } - void deallocate(void * ptr) - { - return ::free(ptr); - } - }; +class StandardAllocator +{ +public: + // not really called + void* allocate(size_t size) { return ::malloc(size); } + void deallocate(void* ptr) { return ::free(ptr); } +}; - template - class AlignedAllocator - { - public: - void* allocate(size_t size) - { - return alignedAllocate(size, ALIGNMENT); - } - void deallocate(void * ptr) - { - return alignedDeallocate(ptr); - } - }; +template +class AlignedAllocator +{ +public: + void* allocate(size_t size) { return alignedAllocate(size, ALIGNMENT); } + void deallocate(void* ptr) { return alignedDeallocate(ptr); } +}; - template - class AllocateMethod +template +class AllocateMethod +{ +public: + static inline T* allocateArray(Index count) { - public: - static inline T* allocateArray(Index count) + TAllocator allocator; + T* rs = (T*)allocator.allocate(count * sizeof(T)); + if (!std::is_trivially_constructible::value) { - TAllocator allocator; - T* rs = (T*)allocator.allocate(count * sizeof(T)); - if (!std::is_trivially_constructible::value) - { - for (Index i = 0; i < count; i++) - new (rs + i) T(); - } - return rs; + for (Index i = 0; i < count; i++) + new (rs + i) T(); } - static inline void deallocateArray(T* ptr, Index count) + return rs; + } + static inline void deallocateArray(T* ptr, Index count) + { + TAllocator allocator; + if (!std::is_trivially_destructible::value) { - TAllocator allocator; - if (!std::is_trivially_destructible::value) - { - for (Index i = 0; i < count; i++) - ptr[i].~T(); - } - allocator.deallocate(ptr); + for (Index i = 0; i < count; i++) + ptr[i].~T(); } - }; + allocator.deallocate(ptr); + } +}; #if 0 template @@ -104,6 +92,6 @@ namespace Slang } }; #endif -} +} // namespace Slang #endif diff --git a/source/core/slang-archive-file-system.cpp b/source/core/slang-archive-file-system.cpp index e219fcbb5..9513e6372 100644 --- a/source/core/slang-archive-file-system.cpp +++ b/source/core/slang-archive-file-system.cpp @@ -1,29 +1,28 @@ #include "slang-archive-file-system.h" +#include "../core/slang-castable.h" +#include "slang-blob.h" #include "slang-com-helper.h" #include "slang-com-ptr.h" - -#include "../core/slang-castable.h" - #include "slang-io.h" -#include "slang-string-util.h" -#include "slang-blob.h" - #include "slang-riff-file-system.h" +#include "slang-string-util.h" // Compression systems #include "slang-deflate-compression-system.h" #include "slang-lz4-compression-system.h" // Zip file system -#include "slang-zip-file-system.h" - #include "slang-riff.h" +#include "slang-zip-file-system.h" namespace Slang { -SlangResult loadArchiveFileSystem(const void* data, size_t dataSizeInBytes, ComPtr& outFileSystem) +SlangResult loadArchiveFileSystem( + const void* data, + size_t dataSizeInBytes, + ComPtr& outFileSystem) { ComPtr fileSystem; if (ZipFileSystem::isArchive(data, dataSizeInBytes)) @@ -34,7 +33,7 @@ SlangResult loadArchiveFileSystem(const void* data, size_t dataSizeInBytes, ComP else if (RiffFileSystem::isArchive(data, dataSizeInBytes)) { // It's riff contained (Slang specific) - fileSystem = new RiffFileSystem(nullptr); + fileSystem = new RiffFileSystem(nullptr); } else { @@ -52,26 +51,28 @@ SlangResult loadArchiveFileSystem(const void* data, size_t dataSizeInBytes, ComP outFileSystem = fileSystem; return SLANG_OK; } - -SlangResult createArchiveFileSystem(SlangArchiveType type, ComPtr& outFileSystem) + +SlangResult createArchiveFileSystem( + SlangArchiveType type, + ComPtr& outFileSystem) { switch (type) { - case SLANG_ARCHIVE_TYPE_ZIP: + case SLANG_ARCHIVE_TYPE_ZIP: { return ZipFileSystem::create(outFileSystem); } - case SLANG_ARCHIVE_TYPE_RIFF: + case SLANG_ARCHIVE_TYPE_RIFF: { outFileSystem = new RiffFileSystem(nullptr); return SLANG_OK; } - case SLANG_ARCHIVE_TYPE_RIFF_DEFLATE: + case SLANG_ARCHIVE_TYPE_RIFF_DEFLATE: { outFileSystem = new RiffFileSystem(DeflateCompressionSystem::getSingleton()); return SLANG_OK; } - case SLANG_ARCHIVE_TYPE_RIFF_LZ4: + case SLANG_ARCHIVE_TYPE_RIFF_LZ4: { outFileSystem = new RiffFileSystem(LZ4CompressionSystem::getSingleton()); return SLANG_OK; diff --git a/source/core/slang-archive-file-system.h b/source/core/slang-archive-file-system.h index 13b226019..25bac0812 100644 --- a/source/core/slang-archive-file-system.h +++ b/source/core/slang-archive-file-system.h @@ -2,9 +2,7 @@ #define SLANG_CORE_ARCHIVE_FILE_SYSTEM_H #include "slang-basic.h" - #include "slang-com-ptr.h" - #include "slang-compression-system.h" namespace Slang @@ -12,20 +10,32 @@ namespace Slang class IArchiveFileSystem : public ISlangCastable { - SLANG_COM_INTERFACE(0x5c565aac, 0xe834, 0x41fc, { 0x8b, 0xb, 0x7d, 0x4c, 0xf3, 0x8b, 0x89, 0x50 }); - - /// Loads an archive. - SLANG_NO_THROW virtual SlangResult SLANG_MCALL loadArchive(const void* archive, size_t archiveSizeInBytes) = 0; - /// Get as an archive (that can be saved to disk) - /// NOTE! If the blob is not owned, it's contents can be invalidated by any call to a method of the file system or loss of scope - SLANG_NO_THROW virtual SlangResult SLANG_MCALL storeArchive(bool blobOwnsContent, ISlangBlob** outBlob) = 0; - /// Set the compression - used for any subsequent items added + SLANG_COM_INTERFACE( + 0x5c565aac, + 0xe834, + 0x41fc, + {0x8b, 0xb, 0x7d, 0x4c, 0xf3, 0x8b, 0x89, 0x50}); + + /// Loads an archive. + SLANG_NO_THROW virtual SlangResult SLANG_MCALL + loadArchive(const void* archive, size_t archiveSizeInBytes) = 0; + /// Get as an archive (that can be saved to disk) + /// NOTE! If the blob is not owned, it's contents can be invalidated by any call to a method of + /// the file system or loss of scope + SLANG_NO_THROW virtual SlangResult SLANG_MCALL + storeArchive(bool blobOwnsContent, ISlangBlob** outBlob) = 0; + /// Set the compression - used for any subsequent items added SLANG_NO_THROW virtual void SLANG_MCALL setCompressionStyle(const CompressionStyle& style) = 0; }; -SlangResult loadArchiveFileSystem(const void* data, size_t dataSizeInBytes, ComPtr& outFileSystem); -SlangResult createArchiveFileSystem(SlangArchiveType type, ComPtr& outFileSystem); +SlangResult loadArchiveFileSystem( + const void* data, + size_t dataSizeInBytes, + ComPtr& outFileSystem); +SlangResult createArchiveFileSystem( + SlangArchiveType type, + ComPtr& outFileSystem); -} +} // namespace Slang #endif diff --git a/source/core/slang-array-view.h b/source/core/slang-array-view.h index 50270e0a0..21b6ce113 100644 --- a/source/core/slang-array-view.h +++ b/source/core/slang-array-view.h @@ -6,222 +6,225 @@ namespace Slang { - // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ConstArrayView !!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! ConstArrayView !!!!!!!!!!!!!!!!!!!!!!!!!!!!! - template - class ConstArrayView - { - public: - typedef ConstArrayView ThisType; +template +class ConstArrayView +{ +public: + typedef ConstArrayView ThisType; - SLANG_FORCE_INLINE const T* begin() const { return m_buffer; } - - SLANG_FORCE_INLINE const T* end() const { return m_buffer + m_count; } - - SLANG_FORCE_INLINE Count getCount() const { return m_count; } + SLANG_FORCE_INLINE const T* begin() const { return m_buffer; } - SLANG_FORCE_INLINE const T& operator [](Index idx) const - { - SLANG_ASSERT(idx >= 0 && idx < m_count); - return m_buffer[idx]; - } - - SLANG_FORCE_INLINE const T* getBuffer() const { return m_buffer; } - - template - Index indexOf(const T2& val) const - { - for (Index i = 0; i < m_count; i++) - { - if (m_buffer[i] == val) - return i; - } - return -1; - } + SLANG_FORCE_INLINE const T* end() const { return m_buffer + m_count; } - template - Index lastIndexOf(const T2& val) const - { - for (Index i = m_count - 1; i >= 0; i--) - { - if (m_buffer[i] == val) - return i; - } - return -1; - } + SLANG_FORCE_INLINE Count getCount() const { return m_count; } - template - Index findFirstIndex(const Func& predicate) const - { - for (Index i = 0; i < m_count; i++) - { - if (predicate(m_buffer[i])) - return i; - } - return -1; - } + SLANG_FORCE_INLINE const T& operator[](Index idx) const + { + SLANG_ASSERT(idx >= 0 && idx < m_count); + return m_buffer[idx]; + } - template - Index findLastIndex(const Func& predicate) const - { - for (Index i = m_count - 1; i >= 0; i--) - { - if (predicate(m_buffer[i])) - return i; - } - return -1; - } + SLANG_FORCE_INLINE const T* getBuffer() const { return m_buffer; } - bool containsMemory(const ThisType& rhs) const + template + Index indexOf(const T2& val) const + { + for (Index i = 0; i < m_count; i++) { - return rhs.getBuffer() >= getBuffer() && rhs.end() <= end(); + if (m_buffer[i] == val) + return i; } + return -1; + } - bool operator==(const ThisType& rhs) const + template + Index lastIndexOf(const T2& val) const + { + for (Index i = m_count - 1; i >= 0; i--) { - if (&rhs == this) - { - return true; - } - const Count count = getCount(); - if (count != rhs.getCount()) - { - return false; - } - const T* thisEle = getBuffer(); - const T* rhsEle = rhs.getBuffer(); - for (Index i = 0; i < count; ++i) - { - if (thisEle[i] != rhsEle[i]) - { - return false; - } - } - return true; + if (m_buffer[i] == val) + return i; } - SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } + return -1; + } - ThisType head(Index index) const + template + Index findFirstIndex(const Func& predicate) const + { + for (Index i = 0; i < m_count; i++) { - SLANG_ASSERT(index >= 0 && index <= m_count); - return ThisType(m_buffer, index); + if (predicate(m_buffer[i])) + return i; } - ThisType tail(Index index) const + return -1; + } + + template + Index findLastIndex(const Func& predicate) const + { + for (Index i = m_count - 1; i >= 0; i--) { - SLANG_ASSERT(index >= 0 && index <= m_count); - return ThisType(m_buffer + index, m_count - index); + if (predicate(m_buffer[i])) + return i; } + return -1; + } - ConstArrayView() : - m_buffer(nullptr), - m_count(0) + bool containsMemory(const ThisType& rhs) const + { + return rhs.getBuffer() >= getBuffer() && rhs.end() <= end(); + } + + bool operator==(const ThisType& rhs) const + { + if (&rhs == this) { + return true; } - - ConstArrayView(const T* buffer, Count count) : - m_buffer(const_cast(buffer)), - m_count(count) + const Count count = getCount(); + if (count != rhs.getCount()) { + return false; } - - protected: - ConstArrayView(T* buffer, Count count) : - m_buffer(buffer), - m_count(count) + const T* thisEle = getBuffer(); + const T* rhsEle = rhs.getBuffer(); + for (Index i = 0; i < count; ++i) { + if (thisEle[i] != rhsEle[i]) + { + return false; + } } + return true; + } + SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - T* m_buffer; ///< Note that this isn't const, as is used for derived class ArrayView also - Count m_count; - }; + ThisType head(Index index) const + { + SLANG_ASSERT(index >= 0 && index <= m_count); + return ThisType(m_buffer, index); + } + ThisType tail(Index index) const + { + SLANG_ASSERT(index >= 0 && index <= m_count); + return ThisType(m_buffer + index, m_count - index); + } - template - ConstArrayView makeConstArrayViewSingle(const T& obj) + ConstArrayView() + : m_buffer(nullptr), m_count(0) { - return ConstArrayView(&obj, 1); - } + } - template - ConstArrayView makeConstArrayView(const T* buffer, Count count) + ConstArrayView(const T* buffer, Count count) + : m_buffer(const_cast(buffer)), m_count(count) { - return ConstArrayView(buffer, count); } - template - ConstArrayView makeConstArrayView(const T (&arr)[N]) +protected: + ConstArrayView(T* buffer, Count count) + : m_buffer(buffer), m_count(count) { - return ConstArrayView(arr, Index(N)); } + T* m_buffer; ///< Note that this isn't const, as is used for derived class ArrayView also + Count m_count; +}; - // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArrayView !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +template +ConstArrayView makeConstArrayViewSingle(const T& obj) +{ + return ConstArrayView(&obj, 1); +} - template - class ArrayView: public ConstArrayView - { - public: - typedef ArrayView ThisType; +template +ConstArrayView makeConstArrayView(const T* buffer, Count count) +{ + return ConstArrayView(buffer, count); +} - typedef ConstArrayView Super; - - using Super::m_buffer; - using Super::m_count; +template +ConstArrayView makeConstArrayView(const T (&arr)[N]) +{ + return ConstArrayView(arr, Index(N)); +} - using Super::begin; - T* begin() { return m_buffer; } - using Super::end; - T* end() { return m_buffer + m_count; } - - using Super::head; - using Super::tail; +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArrayView !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - using Super::operator[]; - inline T& operator [](Index idx) - { - SLANG_ASSERT(idx >= 0 && idx < m_count); - return m_buffer[idx]; - } +template +class ArrayView : public ConstArrayView +{ +public: + typedef ArrayView ThisType; - using Super::getBuffer; - inline T* getBuffer() { return m_buffer; } + typedef ConstArrayView Super; - ThisType head(Index index) - { - SLANG_ASSERT(index >= 0 && index <= m_count); - return ThisType(m_buffer, index); - } - ThisType tail(Index index) - { - SLANG_ASSERT(index >= 0 && index <= m_count); - return ThisType(m_buffer + index, m_count - index); - } + using Super::m_buffer; + using Super::m_count; + + using Super::begin; + T* begin() { return m_buffer; } - T& getLast() { return m_buffer[m_count - 1]; } + using Super::end; + T* end() { return m_buffer + m_count; } - ArrayView() : Super() {} - ArrayView(T* buffer, Index size) :Super(buffer, size) {} - }; + using Super::head; + using Super::tail; - template - ArrayView makeArrayViewSingle(T& obj) + using Super::operator[]; + inline T& operator[](Index idx) { - return ArrayView(&obj, 1); - } - - template - ArrayView makeArrayView(T* buffer, Count count) + SLANG_ASSERT(idx >= 0 && idx < m_count); + return m_buffer[idx]; + } + + using Super::getBuffer; + inline T* getBuffer() { return m_buffer; } + + ThisType head(Index index) { - return ArrayView(buffer, count); + SLANG_ASSERT(index >= 0 && index <= m_count); + return ThisType(m_buffer, index); } + ThisType tail(Index index) + { + SLANG_ASSERT(index >= 0 && index <= m_count); + return ThisType(m_buffer + index, m_count - index); + } + + T& getLast() { return m_buffer[m_count - 1]; } - template - ArrayView makeArrayView(T (&arr)[N]) + ArrayView() + : Super() { - return ArrayView(arr, Count(N)); } + ArrayView(T* buffer, Index size) + : Super(buffer, size) + { + } +}; + +template +ArrayView makeArrayViewSingle(T& obj) +{ + return ArrayView(&obj, 1); +} +template +ArrayView makeArrayView(T* buffer, Count count) +{ + return ArrayView(buffer, count); +} +template +ArrayView makeArrayView(T (&arr)[N]) +{ + return ArrayView(arr, Count(N)); } + +} // namespace Slang + #endif diff --git a/source/core/slang-array.h b/source/core/slang-array.h index d24ff0970..5c2fefc26 100644 --- a/source/core/slang-array.h +++ b/source/core/slang-array.h @@ -1,197 +1,220 @@ #ifndef SLANG_CORE_ARRAY_H #define SLANG_CORE_ARRAY_H -#include "slang-exception.h" #include "slang-array-view.h" +#include "slang-exception.h" namespace Slang { - /* An array container with fixed maximum size defined by COUNT. */ - template - class Array - { - public: - T* begin() { return m_buffer; } - const T* begin() const { return m_buffer; } - - const T* end() const { return m_buffer + m_count; } - T* end() { return m_buffer + m_count; } - - inline Index getCapacity() const { return COUNT; } - inline Index getCount() const { return m_count; } - inline const T& getFirst() const - { - SLANG_ASSERT(m_count > 0); - return m_buffer[0]; - } - inline T& getFirst() - { - SLANG_ASSERT(m_count > 0); - return m_buffer[0]; - } - inline const T& getLast() const - { - SLANG_ASSERT(m_count > 0); - return m_buffer[m_count - 1]; - } - inline T& getLast() - { - SLANG_ASSERT(m_count > 0); - return m_buffer[m_count - 1]; - } - inline void setCount(Index newCount) - { - SLANG_ASSERT(newCount >= 0 && newCount <= COUNT); - m_count = newCount; - } - inline void add(const T& item) - { - SLANG_ASSERT(m_count < COUNT); - m_buffer[m_count++] = item; - } - inline void add(T&& item) - { - SLANG_ASSERT(m_count < COUNT); - m_buffer[m_count++] = _Move(item); - } - - inline const T& operator [](Index idx) const - { - SLANG_ASSERT(idx >= 0 && idx < m_count); - return m_buffer[idx]; - } - inline T& operator [](Index idx) - { - SLANG_ASSERT(idx >= 0 && idx < m_count); - return m_buffer[idx]; - } - - inline const T* getBuffer() const { return m_buffer; } - inline T* getBuffer() { return m_buffer; } - - inline void clear() { m_count = 0; } - - template - Index indexOf(const T2& val) const { return getView().indexOf(val); } - template - Index lastIndexOf(const T2& val) const { return getView().lastIndexOf(val); } - template - Index findFirstIndex(const Func& predicate) const { return getView().findFirstIndex(predicate); } - template - Index findLastIndex(const Func& predicate) const { return getView().findLastIndex(predicate); } - - inline ConstArrayView getView() const { return ConstArrayView(m_buffer, m_count); } - inline ConstArrayView getView(Index start, Index count) const - { - SLANG_ASSERT(start >= 0 && count >= 0); - SLANG_ASSERT(start <= m_count && start + count < m_count); - return ConstArrayView(m_buffer + start, count); - } - - inline ArrayView getView() { return ArrayView(m_buffer, m_count); } - inline ArrayView getView(Index start, Index count) - { - SLANG_ASSERT(start >= 0 && count >= 0); - SLANG_ASSERT(start <= m_count && start + count < m_count); - return ArrayView(m_buffer + start, count); - } - - private: - T m_buffer[COUNT]; - Index m_count = 0; - }; - - template - class Array - { - public: - T* begin() { return nullptr; } - const T* begin() const { return nullptr; } - - const T* end() const { return nullptr; } - T* end() { return nullptr; } - - inline Index getCapacity() const { return 0; } - inline Index getCount() const { return 0; } - inline void setCount(Index newCount) - { - SLANG_ASSERT(newCount == 0); - } - inline const T* getBuffer() const { return nullptr; } - inline T* getBuffer() { return nullptr; } - inline void clear() {} - - template - Index indexOf(const T2& val) const { return getView().indexOf(val); } - template - Index lastIndexOf(const T2& val) const { return getView().lastIndexOf(val); } - template - Index findFirstIndex(const Func& predicate) const { return getView().findFirstIndex(predicate); } - template - Index findLastIndex(const Func& predicate) const { return getView().findLastIndex(predicate); } - - inline ConstArrayView getView() const { return ConstArrayView(nullptr, 0); } - inline ConstArrayView getView(Index start, Index count) const - { - SLANG_ASSERT(start == 0 && count == 0); - return ConstArrayView(nullptr, 0); - } - - inline ArrayView getView() { return ArrayView(nullptr, 0); } - inline ArrayView getView(Index start, Index count) - { - SLANG_ASSERT(start == 0 && count == 0); - return ArrayView(nullptr, 0); - } - }; - - template - struct FirstType - { - typedef T Type; - }; - - - template - void insertArray(Array&) {} - - template - void insertArray(Array& arr, const T& val, TArgs... args) - { - arr.add(val); - insertArray(arr, args...); - } - - template - auto makeArray(TArgs ...args) -> Array::Type, sizeof...(args)> - { - Array::Type, Index(sizeof...(args))> rs; - insertArray::Type>(rs, args...); - return rs; - } - - template - auto makeArray() -> Array - { - return Array(); - } - - - template - void addToList(TList&) - { - } - template - void addToList(TList& list, T node) - { - list.add(node); - } - template - void addToList(TList& list, T node, TArgs ... args) - { - list.add(node); - addToList(list, args...); +/* An array container with fixed maximum size defined by COUNT. */ +template +class Array +{ +public: + T* begin() { return m_buffer; } + const T* begin() const { return m_buffer; } + + const T* end() const { return m_buffer + m_count; } + T* end() { return m_buffer + m_count; } + + inline Index getCapacity() const { return COUNT; } + inline Index getCount() const { return m_count; } + inline const T& getFirst() const + { + SLANG_ASSERT(m_count > 0); + return m_buffer[0]; + } + inline T& getFirst() + { + SLANG_ASSERT(m_count > 0); + return m_buffer[0]; + } + inline const T& getLast() const + { + SLANG_ASSERT(m_count > 0); + return m_buffer[m_count - 1]; + } + inline T& getLast() + { + SLANG_ASSERT(m_count > 0); + return m_buffer[m_count - 1]; + } + inline void setCount(Index newCount) + { + SLANG_ASSERT(newCount >= 0 && newCount <= COUNT); + m_count = newCount; + } + inline void add(const T& item) + { + SLANG_ASSERT(m_count < COUNT); + m_buffer[m_count++] = item; + } + inline void add(T&& item) + { + SLANG_ASSERT(m_count < COUNT); + m_buffer[m_count++] = _Move(item); + } + + inline const T& operator[](Index idx) const + { + SLANG_ASSERT(idx >= 0 && idx < m_count); + return m_buffer[idx]; + } + inline T& operator[](Index idx) + { + SLANG_ASSERT(idx >= 0 && idx < m_count); + return m_buffer[idx]; + } + + inline const T* getBuffer() const { return m_buffer; } + inline T* getBuffer() { return m_buffer; } + + inline void clear() { m_count = 0; } + + template + Index indexOf(const T2& val) const + { + return getView().indexOf(val); + } + template + Index lastIndexOf(const T2& val) const + { + return getView().lastIndexOf(val); + } + template + Index findFirstIndex(const Func& predicate) const + { + return getView().findFirstIndex(predicate); + } + template + Index findLastIndex(const Func& predicate) const + { + return getView().findLastIndex(predicate); + } + + inline ConstArrayView getView() const { return ConstArrayView(m_buffer, m_count); } + inline ConstArrayView getView(Index start, Index count) const + { + SLANG_ASSERT(start >= 0 && count >= 0); + SLANG_ASSERT(start <= m_count && start + count < m_count); + return ConstArrayView(m_buffer + start, count); + } + + inline ArrayView getView() { return ArrayView(m_buffer, m_count); } + inline ArrayView getView(Index start, Index count) + { + SLANG_ASSERT(start >= 0 && count >= 0); + SLANG_ASSERT(start <= m_count && start + count < m_count); + return ArrayView(m_buffer + start, count); } + +private: + T m_buffer[COUNT]; + Index m_count = 0; +}; + +template +class Array +{ +public: + T* begin() { return nullptr; } + const T* begin() const { return nullptr; } + + const T* end() const { return nullptr; } + T* end() { return nullptr; } + + inline Index getCapacity() const { return 0; } + inline Index getCount() const { return 0; } + inline void setCount(Index newCount) { SLANG_ASSERT(newCount == 0); } + inline const T* getBuffer() const { return nullptr; } + inline T* getBuffer() { return nullptr; } + inline void clear() {} + + template + Index indexOf(const T2& val) const + { + return getView().indexOf(val); + } + template + Index lastIndexOf(const T2& val) const + { + return getView().lastIndexOf(val); + } + template + Index findFirstIndex(const Func& predicate) const + { + return getView().findFirstIndex(predicate); + } + template + Index findLastIndex(const Func& predicate) const + { + return getView().findLastIndex(predicate); + } + + inline ConstArrayView getView() const { return ConstArrayView(nullptr, 0); } + inline ConstArrayView getView(Index start, Index count) const + { + SLANG_ASSERT(start == 0 && count == 0); + return ConstArrayView(nullptr, 0); + } + + inline ArrayView getView() { return ArrayView(nullptr, 0); } + inline ArrayView getView(Index start, Index count) + { + SLANG_ASSERT(start == 0 && count == 0); + return ArrayView(nullptr, 0); + } +}; + +template +struct FirstType +{ + typedef T Type; +}; + + +template +void insertArray(Array&) +{ +} + +template +void insertArray(Array& arr, const T& val, TArgs... args) +{ + arr.add(val); + insertArray(arr, args...); +} + +template +auto makeArray(TArgs... args) -> Array::Type, sizeof...(args)> +{ + Array::Type, Index(sizeof...(args))> rs; + insertArray::Type>(rs, args...); + return rs; +} + +template +auto makeArray() -> Array +{ + return Array(); +} + + +template +void addToList(TList&) +{ +} +template +void addToList(TList& list, T node) +{ + list.add(node); +} +template +void addToList(TList& list, T node, TArgs... args) +{ + list.add(node); + addToList(list, args...); } +} // namespace Slang #endif diff --git a/source/core/slang-basic.h b/source/core/slang-basic.h index 5387af4aa..d37782160 100644 --- a/source/core/slang-basic.h +++ b/source/core/slang-basic.h @@ -1,14 +1,14 @@ #ifndef SLANG_CORE_BASIC_H #define SLANG_CORE_BASIC_H -#include "slang-common.h" -#include "slang-math.h" -#include "slang-string.h" #include "slang-array.h" +#include "slang-common.h" +#include "slang-dictionary.h" +#include "slang-exception.h" #include "slang-list.h" +#include "slang-math.h" #include "slang-short-list.h" #include "slang-smart-pointer.h" -#include "slang-exception.h" -#include "slang-dictionary.h" +#include "slang-string.h" #endif diff --git a/source/core/slang-blob.cpp b/source/core/slang-blob.cpp index 19a4281bd..ea4f4b6c0 100644 --- a/source/core/slang-blob.cpp +++ b/source/core/slang-blob.cpp @@ -1,13 +1,13 @@ #include "slang-blob.h" -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! BlobBase !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ ISlangUnknown* BlobBase::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ISlangBlob::getTypeGuid()) + if (guid == ISlangUnknown::getTypeGuid() || guid == ISlangBlob::getTypeGuid()) { return static_cast(this); } @@ -41,12 +41,11 @@ void StringBlob::_setUniqueRep(StringRepresentation* uniqueRep) m_uniqueRep = uniqueRep; - m_slice = uniqueRep ? - UnownedTerminatedStringSlice(uniqueRep->getData(), uniqueRep->getLength()) : - UnownedTerminatedStringSlice(); + m_slice = uniqueRep ? UnownedTerminatedStringSlice(uniqueRep->getData(), uniqueRep->getLength()) + : UnownedTerminatedStringSlice(); } -/* static */StringRepresentation* StringBlob::_createUniqueCopy(StringRepresentation* rep) +/* static */ StringRepresentation* StringBlob::_createUniqueCopy(StringRepresentation* rep) { if (rep) { @@ -75,7 +74,7 @@ void StringBlob::_setWithMove(StringRepresentation* rep) if (rep && !rep->isUniquelyReferenced()) { _setUniqueRep(_createUniqueCopy(rep)); - // We need to release a ref as rep is passed in with the 'current' ref count + // We need to release a ref as rep is passed in with the 'current' ref count rep->releaseReference(); } else @@ -84,7 +83,7 @@ void StringBlob::_setWithMove(StringRepresentation* rep) } } -/* static */ComPtr StringBlob::create(const UnownedStringSlice& slice) +/* static */ ComPtr StringBlob::create(const UnownedStringSlice& slice) { StringRepresentation* rep = nullptr; if (slice.getLength()) @@ -93,27 +92,27 @@ void StringBlob::_setWithMove(StringRepresentation* rep) } auto blob = new StringBlob; - + // rep must be unique at this point blob->_setUniqueRep(rep); return ComPtr(blob); } -/* static */ComPtr StringBlob::create(const String& in) +/* static */ ComPtr StringBlob::create(const String& in) { auto blob = new StringBlob; blob->_setWithCopy(in.getStringRepresentation()); return ComPtr(blob); } -/* static */ComPtr StringBlob::moveCreate(String& in) +/* static */ ComPtr StringBlob::moveCreate(String& in) { auto blob = new StringBlob; blob->_setWithMove(in.detachStringRepresentation()); return ComPtr(blob); } -/* static */ComPtr StringBlob::moveCreate(String&& in) +/* static */ ComPtr StringBlob::moveCreate(String&& in) { auto blob = new StringBlob; blob->_setWithMove(in.detachStringRepresentation()); @@ -167,7 +166,7 @@ void* RawBlob::getObject(const Guid& guid) // If the data has 0 termination, we can return the pointer if (guid == SlangTerminatedChars::getTypeGuid() && m_data.isTerminated()) { - return (char*)m_data.getData(); + return (char*)m_data.getData(); } return nullptr; } @@ -185,7 +184,7 @@ void* ScopeBlob::castAs(const SlangUUID& guid) return obj; } - // If the contained thing is castable, ask it + // If the contained thing is castable, ask it if (m_castable) { return m_castable->castAs(guid); @@ -225,7 +224,7 @@ void* ListBlob::getObject(const Guid& guid) /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! StaticBlob !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ -SlangResult StaticBlob::queryInterface(SlangUUID const& guid, void** outObject) +SlangResult StaticBlob::queryInterface(SlangUUID const& guid, void** outObject) { if (auto intf = getInterface(guid)) { @@ -246,8 +245,7 @@ void* StaticBlob::castAs(const SlangUUID& guid) ISlangUnknown* StaticBlob::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ISlangBlob::getTypeGuid()) + if (guid == ISlangUnknown::getTypeGuid() || guid == ISlangBlob::getTypeGuid()) { return static_cast(this); } diff --git a/source/core/slang-blob.h b/source/core/slang-blob.h index 4df8f0db6..af3206fb5 100644 --- a/source/core/slang-blob.h +++ b/source/core/slang-blob.h @@ -1,22 +1,20 @@ #ifndef SLANG_CORE_BLOB_H #define SLANG_CORE_BLOB_H -#include "slang.h" - -#include "slang-string.h" -#include "slang-list.h" - -#include - +#include "../core/slang-com-object.h" #include "slang-com-helper.h" #include "slang-com-ptr.h" +#include "slang-list.h" +#include "slang-string.h" +#include "slang.h" -#include "../core/slang-com-object.h" +#include -namespace Slang { +namespace Slang +{ /** Base class for simple blobs. -*/ + */ class BlobBase : public ISlangBlob, public ICastable, public ComBaseObject { public: @@ -33,53 +31,57 @@ protected: /** A blob that uses a `StringRepresentation` for its storage. -By design the StringBlob owns a unique reference to the StringRepresentation. +By design the StringBlob owns a unique reference to the StringRepresentation. This is because StringBlob, implements an interface which should work across threads. */ class StringBlob : public BlobBase { public: - SLANG_CLASS_GUID(0xf7e0e93c, 0xde70, 0x4531, { 0x9c, 0x9f, 0xdd, 0xa3, 0xf6, 0xc6, 0xc0, 0xdd }); + SLANG_CLASS_GUID(0xf7e0e93c, 0xde70, 0x4531, {0x9c, 0x9f, 0xdd, 0xa3, 0xf6, 0xc6, 0xc0, 0xdd}); // ICastable virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const SlangUUID& guid) SLANG_OVERRIDE; // ISlangBlob - SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_slice.begin(); } + SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE + { + return m_slice.begin(); + } SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_slice.getLength(); } - /// Since in is not being moved will *always* create a new representation, unless the in is empty + /// Since in is not being moved will *always* create a new representation, unless the in is + /// empty static ComPtr create(const String& in); - /// Create from a slice + /// Create from a slice static ComPtr create(const UnownedStringSlice& slice); - /// Moves from in into the created blob. - /// NOTE! That will only use the representation from in, if it is *unique* - /// otherwise it will make a new copy. + /// Moves from in into the created blob. + /// NOTE! That will only use the representation from in, if it is *unique* + /// otherwise it will make a new copy. static ComPtr moveCreate(String& in); static ComPtr moveCreate(String&& in); - /// Dtor + /// Dtor ~StringBlob(); protected: - - /// Init with a rep when can't be owned. + /// Init with a rep when can't be owned. void _setWithCopy(StringRepresentation* rep); - /// Init with a representation that has been moved. + /// Init with a representation that has been moved. void _setWithMove(StringRepresentation* rep); - /// Create a unique copy of rep. - /// If nullptr will work (if rep is empty, will return that) + /// Create a unique copy of rep. + /// If nullptr will work (if rep is empty, will return that) static StringRepresentation* _createUniqueCopy(StringRepresentation* rep); - /// Rep can only be nullptr or have a single ref + /// Rep can only be nullptr or have a single ref void _setUniqueRep(StringRepresentation* rep); void* getObject(const Guid& guid); - UnownedTerminatedStringSlice m_slice; ///< The contents - StringRepresentation* m_uniqueRep = nullptr; ///< Holds actual bytes. Can be nullptr if it's an empty string. + UnownedTerminatedStringSlice m_slice; ///< The contents + StringRepresentation* m_uniqueRep = + nullptr; ///< Holds actual bytes. Can be nullptr if it's an empty string. }; class ListBlob : public BlobBase @@ -91,17 +93,32 @@ public: // ICastable virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const SlangUUID& guid) SLANG_OVERRIDE; // ISlangBlob - SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_data.getBuffer(); } + SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE + { + return m_data.getBuffer(); + } SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_data.getCount(); } - static ComPtr create(const List& data) { return ComPtr(new ListBlob(data)); } - - static ComPtr moveCreate(List& data) { return ComPtr(new ListBlob(_Move(data))); } + static ComPtr create(const List& data) + { + return ComPtr(new ListBlob(data)); + } + + static ComPtr moveCreate(List& data) + { + return ComPtr(new ListBlob(_Move(data))); + } protected: - explicit ListBlob(const List& data) : m_data(data) {} - // Move ctor - explicit ListBlob(List&& data) : m_data(data) {} + explicit ListBlob(const List& data) + : m_data(data) + { + } + // Move ctor + explicit ListBlob(List&& data) + : m_data(data) + { + } void* getObject(const Guid& guid); @@ -126,7 +143,7 @@ public: m_capacityInBytes = size; return m_data; } - /// Allocate size including a 0 byte at `size`. + /// Allocate size including a 0 byte at `size`. void* allocateTerminated(size_t size) { SLANG_ASSUME(size != std::numeric_limits::max()); @@ -146,7 +163,8 @@ public: m_sizeInBytes = 0; m_capacityInBytes = 0; } - // Reallocate so the buffer is the specified capacity/size. Contents of buffer up to size remain intact. + // Reallocate so the buffer is the specified capacity/size. Contents of buffer up to size remain + // intact. void reallocate(size_t capacity) { if (capacity != m_capacityInBytes) @@ -156,7 +174,8 @@ public: m_capacityInBytes = capacity; } } - /// Makes this no longer own the allocation. Returns the allocated data (or nullptr if no allocation) + /// Makes this no longer own the allocation. Returns the allocated data (or nullptr if no + /// allocation) void* detach() { void* data = m_data; @@ -185,14 +204,14 @@ public: return dst; } - /// Get the allocated data. Returns nullptr if there is no allocated data + /// Get the allocated data. Returns nullptr if there is no allocated data void* getData() const { return m_data; } - /// Get the size of the allocated data. + /// Get the size of the allocated data. size_t getSizeInBytes() const { return m_sizeInBytes; } - /// Get the capacity in bytes + /// Get the capacity in bytes size_t getCapacityInBytes() const { return m_capacityInBytes; } - void setSizeInBytes(size_t size) + void setSizeInBytes(size_t size) { SLANG_ASSERT(size <= m_capacityInBytes); m_sizeInBytes = size; @@ -205,13 +224,14 @@ public: Swap(m_capacityInBytes, rhs.m_capacityInBytes); } - /// True if has zero termination, at the byte at m_sizeInBytes - bool isTerminated() const { return m_capacityInBytes > m_sizeInBytes && ((const char*)m_data)[m_sizeInBytes] == 0; } + /// True if has zero termination, at the byte at m_sizeInBytes + bool isTerminated() const + { + return m_capacityInBytes > m_sizeInBytes && ((const char*)m_data)[m_sizeInBytes] == 0; + } - ScopedAllocation() : - m_data(nullptr), - m_sizeInBytes(0), - m_capacityInBytes(0) + ScopedAllocation() + : m_data(nullptr), m_sizeInBytes(0), m_capacityInBytes(0) { } @@ -228,15 +248,21 @@ private: }; /** A blob that manages some raw data that it owns. -*/ + */ class RawBlob : public BlobBase { public: // ICastable virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const SlangUUID& guid) SLANG_OVERRIDE; // ISlangBlob - SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_data.getData(); } - SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_data.getSizeInBytes(); } + SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE + { + return m_data.getData(); + } + SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE + { + return m_data.getSizeInBytes(); + } static ComPtr moveCreate(ScopedAllocation& alloc) { @@ -245,7 +271,7 @@ public: return ComPtr(blob); } - /// Create a blob that will retain (a copy of) raw data. + /// Create a blob that will retain (a copy of) raw data. static inline ComPtr create(void const* inData, size_t size) { return ComPtr(new RawBlob(inData, size)); @@ -254,10 +280,7 @@ public: protected: // Ctor // NOTE! Takes a copy of the input data - RawBlob(const void* data, size_t size) - { - memcpy(m_data.allocateTerminated(size), data, size); - } + RawBlob(const void* data, size_t size) { memcpy(m_data.allocateTerminated(size), data, size); } void* getObject(const Guid& guid); @@ -281,9 +304,8 @@ public: protected: // Ctor - UnownedRawBlob(const void* data, size_t size) : - m_data(data), - m_dataSizeInBytes(size) + UnownedRawBlob(const void* data, size_t size) + : m_data(data), m_dataSizeInBytes(size) { } @@ -300,9 +322,9 @@ This is useful when a Blob is useful to represent some global immutable chunk of class StaticBlob : public ISlangBlob, public ICastable { public: - // ISlangUnknown - SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) SLANG_OVERRIDE; + SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) + SLANG_OVERRIDE; SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return 1; } SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return 1; } @@ -313,9 +335,8 @@ public: SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_data; } SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_dataCount; } - StaticBlob(const void* data, size_t dataCount): - m_data(data), - m_dataCount(dataCount) + StaticBlob(const void* data, size_t dataCount) + : m_data(data), m_dataCount(dataCount) { } @@ -334,8 +355,14 @@ public: virtual SLANG_NO_THROW void* SLANG_MCALL castAs(const SlangUUID& guid) SLANG_OVERRIDE; // ISlangBlob - SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE { return m_blob->getBufferPointer(); } - SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE { return m_blob->getBufferSize(); } + SLANG_NO_THROW void const* SLANG_MCALL getBufferPointer() SLANG_OVERRIDE + { + return m_blob->getBufferPointer(); + } + SLANG_NO_THROW size_t SLANG_MCALL getBufferSize() SLANG_OVERRIDE + { + return m_blob->getBufferSize(); + } static inline ComPtr create(ISlangBlob* blob, ISlangUnknown* scope) { @@ -343,11 +370,9 @@ public: } protected: - // Ctor - ScopeBlob(ISlangBlob* blob, ISlangUnknown* scope) : - m_blob(blob), - m_scope(scope) + ScopeBlob(ISlangBlob* blob, ISlangUnknown* scope) + : m_blob(blob), m_scope(scope) { // Cache the ICastable interface if there is one. blob->queryInterface(SLANG_IID_PPV_ARGS(m_castable.writeRef())); @@ -355,7 +380,8 @@ protected: ComPtr m_scope; ComPtr m_blob; - ComPtr m_castable; ///< Set if the blob has this interface. Set to nullptr if does not. + ComPtr + m_castable; ///< Set if the blob has this interface. Set to nullptr if does not. }; } // namespace Slang diff --git a/source/core/slang-byte-encode-util.cpp b/source/core/slang-byte-encode-util.cpp index c7022397f..acafdf2b4 100644 --- a/source/core/slang-byte-encode-util.cpp +++ b/source/core/slang-byte-encode-util.cpp @@ -1,17 +1,18 @@ #include "slang-byte-encode-util.h" -namespace Slang { +namespace Slang +{ // Descriptions of algorithms here... // https://github.com/stoklund/varint #if SLANG_LITTLE_ENDIAN && SLANG_UNALIGNED_ACCESS // Testing on i7, unaligned access is around 40% faster -# define SLANG_BYTE_ENCODE_USE_UNALIGNED_ACCESS 1 +#define SLANG_BYTE_ENCODE_USE_UNALIGNED_ACCESS 1 #endif #ifndef SLANG_BYTE_ENCODE_USE_UNALIGNED_ACCESS -# define SLANG_BYTE_ENCODE_USE_UNALIGNED_ACCESS 0 +#define SLANG_BYTE_ENCODE_USE_UNALIGNED_ACCESS 0 #endif #define SLANG_REPEAT_2(n) n, n @@ -22,23 +23,22 @@ namespace Slang { #define SLANG_REPEAT_64(n) SLANG_REPEAT_32(n), SLANG_REPEAT_32(n) #define SLANG_REPEAT_128(n) SLANG_REPEAT_64(n), SLANG_REPEAT_64(n) -/* static */const int8_t ByteEncodeUtil::s_msb8[256] = -{ - - 1, - 0, - SLANG_REPEAT_2(1), - SLANG_REPEAT_4(2), - SLANG_REPEAT_8(3), - SLANG_REPEAT_16(4), +/* static */ const int8_t ByteEncodeUtil::s_msb8[256] = { + -1, + 0, + SLANG_REPEAT_2(1), + SLANG_REPEAT_4(2), + SLANG_REPEAT_8(3), + SLANG_REPEAT_16(4), SLANG_REPEAT_32(5), SLANG_REPEAT_64(6), SLANG_REPEAT_128(7), }; -/* static */size_t ByteEncodeUtil::calcEncodeLiteSizeUInt32(const uint32_t* in, size_t num) +/* static */ size_t ByteEncodeUtil::calcEncodeLiteSizeUInt32(const uint32_t* in, size_t num) { size_t totalNumEncodeBytes = 0; - + for (size_t i = 0; i < num; i++) { const uint32_t v = in[i]; @@ -59,7 +59,10 @@ namespace Slang { return totalNumEncodeBytes; } -/* static */size_t ByteEncodeUtil::encodeLiteUInt32(const uint32_t* in, size_t num, uint8_t* encodeOut) +/* static */ size_t ByteEncodeUtil::encodeLiteUInt32( + const uint32_t* in, + size_t num, + uint8_t* encodeOut) { uint8_t* encodeStart = encodeOut; @@ -67,7 +70,7 @@ namespace Slang { { uint32_t v = in[i]; - if(v < kLiteCut1) + if (v < kLiteCut1) { *encodeOut++ = uint8_t(v); } @@ -95,7 +98,10 @@ namespace Slang { return size_t(encodeOut - encodeStart); } -/* static */void ByteEncodeUtil::encodeLiteUInt32(const uint32_t* in, size_t num, List& encodeArrayOut) +/* static */ void ByteEncodeUtil::encodeLiteUInt32( + const uint32_t* in, + size_t num, + List& encodeArrayOut) { // Make sure there is at least enough space for all bytes encodeArrayOut.setCount(num); @@ -111,7 +117,7 @@ namespace Slang { const size_t offset = size_t(encodeOut - encodeArrayOut.begin()); const UInt oldCapacity = encodeArrayOut.getCapacity(); - + // Make some more space encodeArrayOut.reserve(oldCapacity + (oldCapacity >> 1) + kMaxLiteEncodeUInt32); // Make the size the capacity @@ -154,7 +160,7 @@ namespace Slang { encodeArrayOut.compress(); } -/* static */int ByteEncodeUtil::encodeLiteUInt32(uint32_t in, uint8_t out[kMaxLiteEncodeUInt32]) +/* static */ int ByteEncodeUtil::encodeLiteUInt32(uint32_t in, uint8_t out[kMaxLiteEncodeUInt32]) { // 0-184 1 byte value = B0 // 185 - 248 2 bytes value = 185 + 256 * (B0 - 185) + B1 @@ -187,8 +193,7 @@ namespace Slang { } } -static const uint32_t s_unalignedUInt32Mask[5] = -{ +static const uint32_t s_unalignedUInt32Mask[5] = { 0x00000000, 0x000000ff, 0x0000ffff, @@ -196,8 +201,8 @@ static const uint32_t s_unalignedUInt32Mask[5] = 0xffffffff, }; -// Decode the >= kLiteCut2. -// in is pointing past the first byte. +// Decode the >= kLiteCut2. +// in is pointing past the first byte. // Only valid numBytesRemaining is 2, 3, or 4 SLANG_FORCE_INLINE static uint32_t _decodeLiteCut2UInt32(const uint8_t* in, int numBytesRemaining) { @@ -205,26 +210,26 @@ SLANG_FORCE_INLINE static uint32_t _decodeLiteCut2UInt32(const uint8_t* in, int #if SLANG_BYTE_ENCODE_USE_UNALIGNED_ACCESS switch (numBytesRemaining) { - case 2: value = *(const uint16_t*)in; break; - case 3: value = (uint32_t(in[2]) << 16) | (uint32_t(in[1]) << 8) | uint32_t(in[0]); break; - case 4: value = *(const uint32_t*)in; break; - default: break; + case 2: value = *(const uint16_t*)in; break; + case 3: value = (uint32_t(in[2]) << 16) | (uint32_t(in[1]) << 8) | uint32_t(in[0]); break; + case 4: value = *(const uint32_t*)in; break; + default: break; } #else // This works on all cpus although slower value = in[0]; switch (numBytesRemaining) { - case 4: value |= uint32_t(in[3]) << 24; /* fall thru */ - case 3: value |= uint32_t(in[2]) << 16; /* fall thru */ - case 2: value |= uint32_t(in[1]) << 8; /* fall thru */ - case 1: break; + case 4: value |= uint32_t(in[3]) << 24; /* fall thru */ + case 3: value |= uint32_t(in[2]) << 16; /* fall thru */ + case 2: value |= uint32_t(in[1]) << 8; /* fall thru */ + case 1: break; } #endif return value; } -/* static */int ByteEncodeUtil::decodeLiteUInt32(const uint8_t* in, uint32_t* out) +/* static */ int ByteEncodeUtil::decodeLiteUInt32(const uint8_t* in, uint32_t* out) { uint8_t b0 = *in++; if (b0 < kLiteCut1) @@ -246,7 +251,10 @@ SLANG_FORCE_INLINE static uint32_t _decodeLiteCut2UInt32(const uint8_t* in, int } } -/* static */size_t ByteEncodeUtil::decodeLiteUInt32(const uint8_t* encodeIn, size_t numValues, uint32_t* valuesOut) +/* static */ size_t ByteEncodeUtil::decodeLiteUInt32( + const uint8_t* encodeIn, + size_t numValues, + uint32_t* valuesOut) { const uint8_t* encodeStart = encodeIn; @@ -267,13 +275,13 @@ SLANG_FORCE_INLINE static uint32_t _decodeLiteCut2UInt32(const uint8_t* in, int const int numBytesRemaining = b0 - kLiteCut2 + 2 - 1; // For unaligned access, do not use unaligned access for the last two values, - // (3rd last is safe because this value will have at least 2 bytes, followed by at worst two 1-byte values) - // otherwise we can access outside the bounds of the encoded array + // (3rd last is safe because this value will have at least 2 bytes, followed by at worst + // two 1-byte values) otherwise we can access outside the bounds of the encoded array // This prevents memory validation tools from causing an exception here if (SLANG_BYTE_ENCODE_USE_UNALIGNED_ACCESS && i < numValues - 2) { const uint32_t mask = s_unalignedUInt32Mask[numBytesRemaining]; - //const uint32_t mask = ~(uint32_t(0xffffff00) << ((numBytesRemaining - 1) * 8)); + // const uint32_t mask = ~(uint32_t(0xffffff00) << ((numBytesRemaining - 1) * 8)); valuesOut[i] = (*(const uint32_t*)encodeIn) & mask; } else diff --git a/source/core/slang-byte-encode-util.h b/source/core/slang-byte-encode-util.h index 728f9ac2f..81fc0ef98 100644 --- a/source/core/slang-byte-encode-util.h +++ b/source/core/slang-byte-encode-util.h @@ -3,88 +3,90 @@ #include "slang-list.h" -namespace Slang { +namespace Slang +{ struct ByteEncodeUtil { enum { kMaxLiteEncodeUInt16 = 3, /// One byte for prefix, the remaining 2 bytes hold the value - kMaxLiteEncodeUInt32 = 5, /// One byte for prefix, the remaining 4 bytes hold the value + kMaxLiteEncodeUInt32 = 5, /// One byte for prefix, the remaining 4 bytes hold the value // Cut values for 'Lite' encoding style kLiteCut1 = 185, kLiteCut2 = 249, }; - /** Find the most significant bit for 8 bits - @param v The value to find most significant bit on - @return The most significant bit, or -1 if no bits are set - */ + /** Find the most significant bit for 8 bits + @param v The value to find most significant bit on + @return The most significant bit, or -1 if no bits are set + */ SLANG_FORCE_INLINE static int calcMsb8(uint32_t v); - - /** Find the most significant bit for 32 bits - @param v The value to find most significant bit on - @return The most significant bit, or -1 if no bits are set - */ + + /** Find the most significant bit for 32 bits + @param v The value to find most significant bit on + @return The most significant bit, or -1 if no bits are set + */ SLANG_FORCE_INLINE static int calcMsb32(uint32_t v); - - /** Calculates the 'most significant' byte ie the highest bytes that is non zero. - Note return value is *undefined* if in is 0. - @param in Value - cannot be 0. - @return The byte index of the highest byte that is non zero. - */ + + /** Calculates the 'most significant' byte ie the highest bytes that is non zero. + Note return value is *undefined* if in is 0. + @param in Value - cannot be 0. + @return The byte index of the highest byte that is non zero. + */ SLANG_FORCE_INLINE static int calcNonZeroMsByte32(uint32_t in); - /** Calculates the 'most significant' byte ie the highest bytes that is non zero. - @param in Value - cannot be 0. - @return The byte index of the highest byte that is non zero. - */ + /** Calculates the 'most significant' byte ie the highest bytes that is non zero. + @param in Value - cannot be 0. + @return The byte index of the highest byte that is non zero. + */ SLANG_FORCE_INLINE static int calcMsByte32(uint32_t in); - /// Calculate the size of encoding bytes + /// Calculate the size of encoding bytes static size_t calcEncodeLiteSizeUInt32(const uint32_t* in, size_t num); - /// Calculate the size of a single value + /// Calculate the size of a single value static size_t calcEncodeLiteSizeUInt32(uint32_t in); - - /** Encodes a uint32_t as an integer - @return the number of bytes needed to encode */ + + /** Encodes a uint32_t as an integer + @return the number of bytes needed to encode */ static int encodeLiteUInt32(uint32_t in, uint8_t out[kMaxLiteEncodeUInt32]); - /** Decode a lite encoding. - @param in The lite encoded bytes - @param out Value constructed - @return number of bytes on in consumed */ + /** Decode a lite encoding. + @param in The lite encoded bytes + @param out Value constructed + @return number of bytes on in consumed */ static int decodeLiteUInt32(const uint8_t* in, uint32_t* out); - /** Encode an array of uint32_t - @param in The values to encode - @param num The amount of values to encode - @param encodeOut The buffer to hold the encoded value. MUST be large enough to hold the encoding - @return The size of the encoding in bytes - */ + /** Encode an array of uint32_t + @param in The values to encode + @param num The amount of values to encode + @param encodeOut The buffer to hold the encoded value. MUST be large enough to hold the encoding + @return The size of the encoding in bytes + */ static size_t encodeLiteUInt32(const uint32_t* in, size_t num, uint8_t* encodeOut); - /** Encode an array of uint32_t - @param in The values to encode - @param num The amount of values to encode - @param encodeOut The buffer to hold the encoded value. - */ + /** Encode an array of uint32_t + @param in The values to encode + @param num The amount of values to encode + @param encodeOut The buffer to hold the encoded value. + */ static void encodeLiteUInt32(const uint32_t* in, size_t num, List& encodeOut); - /** Encode an array of uint32_t - @param encodeIn The encoded values - @param numValues The amount of values to be decoded (NOTE! This is the number of valuesOut, not encodeIn) - @param valuesOut The buffer to hold the encoded value. MUST be large enough to hold the encoding - @return The amount of bytes decoded - */ - static size_t decodeLiteUInt32(const uint8_t* encodeIn, size_t numValues, uint32_t* valuesOut); + /** Encode an array of uint32_t + @param encodeIn The encoded values + @param numValues The amount of values to be decoded (NOTE! This is the number of valuesOut, not + encodeIn) + @param valuesOut The buffer to hold the encoded value. MUST be large enough to hold the encoding + @return The amount of bytes decoded + */ + static size_t decodeLiteUInt32(const uint8_t* encodeIn, size_t numValues, uint32_t* valuesOut); - /// Table that maps 8 bits to it's most significant bit. If 0 returns -1. + /// Table that maps 8 bits to it's most significant bit. If 0 returns -1. static const int8_t s_msb8[256]; }; -#if SLANG_VC +#if SLANG_VC // Works on ARM and x86/64 on visual studio compiler // --------------------------------------------------------------------------- @@ -102,7 +104,7 @@ SLANG_FORCE_INLINE int ByteEncodeUtil::calcNonZeroMsByte32(uint32_t in) SLANG_FORCE_INLINE int ByteEncodeUtil::calcMsByte32(uint32_t in) { if (in == 0) - { + { return -1; } // Can use intrinsic @@ -113,7 +115,7 @@ SLANG_FORCE_INLINE int ByteEncodeUtil::calcMsByte32(uint32_t in) } // --------------------------------------------------------------------------- -SLANG_FORCE_INLINE /* static */int ByteEncodeUtil::calcMsb8(uint32_t v) +SLANG_FORCE_INLINE /* static */ int ByteEncodeUtil::calcMsb8(uint32_t v) { SLANG_ASSERT((v & 0xffffff00) == 0); if (v == 0) @@ -126,7 +128,7 @@ SLANG_FORCE_INLINE /* static */int ByteEncodeUtil::calcMsb8(uint32_t v) } // --------------------------------------------------------------------------- -SLANG_FORCE_INLINE /* static */int ByteEncodeUtil::calcMsb32(uint32_t v) +SLANG_FORCE_INLINE /* static */ int ByteEncodeUtil::calcMsb32(uint32_t v) { if (v == 0) { @@ -140,41 +142,36 @@ SLANG_FORCE_INLINE /* static */int ByteEncodeUtil::calcMsb32(uint32_t v) #else // --------------------------------------------------------------------------- -SLANG_FORCE_INLINE /* static */int ByteEncodeUtil::calcNonZeroMsByte32(uint32_t in) +SLANG_FORCE_INLINE /* static */ int ByteEncodeUtil::calcNonZeroMsByte32(uint32_t in) { - return (in & 0xffff0000) ? - ((in & 0xff000000) ? 3 : 2) : - ((in & 0x0000ff00) ? 1 : 0); + return (in & 0xffff0000) ? ((in & 0xff000000) ? 3 : 2) : ((in & 0x0000ff00) ? 1 : 0); } // --------------------------------------------------------------------------- -SLANG_FORCE_INLINE /* static */int ByteEncodeUtil::calcMsByte32(uint32_t in) +SLANG_FORCE_INLINE /* static */ int ByteEncodeUtil::calcMsByte32(uint32_t in) { - return (in & 0xffff0000) ? - ((in & 0xff000000) ? 3 : 2) : - ((in & 0x0000ff00) ? 1 : - ((in == 0) ? -1 : 0)); + return (in & 0xffff0000) ? ((in & 0xff000000) ? 3 : 2) + : ((in & 0x0000ff00) ? 1 : ((in == 0) ? -1 : 0)); } // --------------------------------------------------------------------------- -SLANG_FORCE_INLINE /* static */int ByteEncodeUtil::calcMsb8(uint32_t v) -{ - SLANG_ASSERT((v & 0xffffff00) == 0); - return s_msb8[v]; +SLANG_FORCE_INLINE /* static */ int ByteEncodeUtil::calcMsb8(uint32_t v) +{ + SLANG_ASSERT((v & 0xffffff00) == 0); + return s_msb8[v]; } // --------------------------------------------------------------------------- -SLANG_FORCE_INLINE /* static */int ByteEncodeUtil::calcMsb32(uint32_t v) +SLANG_FORCE_INLINE /* static */ int ByteEncodeUtil::calcMsb32(uint32_t v) { - return (v & 0xffff0000) ? - ((v & 0xff000000) ? s_msb8[v >> 24] + 24 : s_msb8[v >> 16] + 16) : - ((v & 0x0000ff00) ? s_msb8[v >> 8] + 8 : s_msb8[v]); + return (v & 0xffff0000) ? ((v & 0xff000000) ? s_msb8[v >> 24] + 24 : s_msb8[v >> 16] + 16) + : ((v & 0x0000ff00) ? s_msb8[v >> 8] + 8 : s_msb8[v]); } #endif // --------------------------------------------------------------------------- -inline /* static */size_t ByteEncodeUtil::calcEncodeLiteSizeUInt32(uint32_t v) +inline /* static */ size_t ByteEncodeUtil::calcEncodeLiteSizeUInt32(uint32_t v) { if (v < kLiteCut1) { diff --git a/source/core/slang-castable.cpp b/source/core/slang-castable.cpp index f3c6541dd..ece87fe2b 100644 --- a/source/core/slang-castable.cpp +++ b/source/core/slang-castable.cpp @@ -1,11 +1,12 @@ // slang-castable.cpp #include "slang-castable.h" -namespace Slang { +namespace Slang +{ /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! CastableUtil !!!!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */ComPtr CastableUtil::getCastable(ISlangUnknown* unk) +/* static */ ComPtr CastableUtil::getCastable(ISlangUnknown* unk) { SLANG_ASSERT(unk); ComPtr castable; @@ -52,8 +53,7 @@ void* UnknownCastableAdapter::castAs(const Guid& guid) void* UnknownCastableAdapter::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IUnknownCastableAdapter::getTypeGuid()) { return static_cast(this); diff --git a/source/core/slang-castable.h b/source/core/slang-castable.h index e2b9c4a8e..50b41766a 100644 --- a/source/core/slang-castable.h +++ b/source/core/slang-castable.h @@ -3,16 +3,15 @@ #define SLANG_CASTABLE_H +#include "../core/slang-com-object.h" #include "slang-com-helper.h" #include "slang-com-ptr.h" -#include "../core/slang-com-object.h" - namespace Slang { // Dynamic cast of ICastable derived types -template +template SLANG_FORCE_INLINE T* dynamicCast(ICastable* castable) { if (castable) @@ -24,7 +23,7 @@ SLANG_FORCE_INLINE T* dynamicCast(ICastable* castable) } // as style cast -template +template SLANG_FORCE_INLINE T* as(ICastable* castable) { if (castable) @@ -36,34 +35,38 @@ SLANG_FORCE_INLINE T* as(ICastable* castable) } /* An interface for boxing values */ -class IBoxValueBase: public ICastable +class IBoxValueBase : public ICastable { - SLANG_COM_INTERFACE(0x8b4aad81, 0x4934, 0x4a67, { 0xb2, 0xe2, 0xe9, 0x17, 0xfc, 0x29, 0x12, 0x54 }); + SLANG_COM_INTERFACE( + 0x8b4aad81, + 0x4934, + 0x4a67, + {0xb2, 0xe2, 0xe9, 0x17, 0xfc, 0x29, 0x12, 0x54}); - /// Get the contained object + /// Get the contained object virtual SLANG_NO_THROW void* SLANG_MCALL getValuePtr() = 0; - /// Get the guid that represents the contained ref object + /// Get the guid that represents the contained ref object virtual SLANG_NO_THROW SlangUUID SLANG_MCALL getValueTypeGuid() = 0; }; -template +template class IBoxValue : public IBoxValueBase { - public: - +public: SLANG_FORCE_INLINE T& get() { return *reinterpret_cast(getValuePtr()); } SLANG_FORCE_INLINE T* getPtr() { return reinterpret_cast(getValuePtr()); } }; // Cast into a boxed value type -template +template SLANG_FORCE_INLINE IBoxValue* asBoxValue(ICastable* castable) { IBoxValueBase* base = as(castable); - return (base && base->getValueTypeGuid() == T::getTypeGuid()) ? static_cast*>(base) : nullptr; + return (base && base->getValueTypeGuid() == T::getTypeGuid()) ? static_cast*>(base) + : nullptr; } -template +template class BoxValue : public ComBaseObject, public IBoxValue { public: @@ -78,24 +81,23 @@ public: BoxValue() {} - explicit BoxValue(const T& rhs): - m_value(rhs) + explicit BoxValue(const T& rhs) + : m_value(rhs) { } protected: - void* getInterface(const Guid& guid); + void* getInterface(const Guid& guid); void* getObject(const Guid& guid); - + T m_value; }; // ------------------------------------------------------------ -template +template void* BoxValue::getInterface(const Guid& guid) { - if (guid == ISlangUnknown::getTypeGuid() || - guid == ICastable::getTypeGuid() || + if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() || guid == IBoxValueBase::getTypeGuid()) { return static_cast(this); @@ -104,7 +106,7 @@ void* BoxValue::getInterface(const Guid& guid) } // ------------------------------------------------------------ -template +template void* BoxValue::getObject(const Guid& guid) { if (guid == T::getTypeGuid()) @@ -115,7 +117,7 @@ void* BoxValue::getObject(const Guid& guid) } // ------------------------------------------------------------ -template +template void* BoxValue::castAs(const Guid& guid) { if (auto ptr = getObject(guid)) @@ -124,22 +126,28 @@ void* BoxValue::castAs(const Guid& guid) } return getInterface(guid); } - + /* Adapter interface to make a non castable types work as ICastable */ class IUnknownCastableAdapter : public ICastable { - SLANG_COM_INTERFACE(0x8b4aad81, 0x4934, 0x4a67, { 0xb2, 0xe2, 0xe9, 0x17, 0xfc, 0x29, 0x12, 0x54 }); + SLANG_COM_INTERFACE( + 0x8b4aad81, + 0x4934, + 0x4a67, + {0xb2, 0xe2, 0xe9, 0x17, 0xfc, 0x29, 0x12, 0x54}); /// When using the adapter, this provides a way to directly get the internal no ICastable type virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getContained() = 0; }; -/* An adapter such that types which aren't derived from ICastable, can be used as such. +/* An adapter such that types which aren't derived from ICastable, can be used as such. With the following caveats. -* the interfaces/objects of the adapter are checked *first*, so IUnknown will always be for the adapter -* assumes when doing a queryInterface on the contained item, it will remain in scope when released (this is *not* strict COM) +* the interfaces/objects of the adapter are checked *first*, so IUnknown will always be for the +adapter +* assumes when doing a queryInterface on the contained item, it will remain in scope when released +(this is *not* strict COM) */ class UnknownCastableAdapter : public ComBaseObject, public IUnknownCastableAdapter { @@ -150,10 +158,13 @@ public: SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE; // IUnknownCastableAdapter - virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getContained() SLANG_OVERRIDE { return m_contained; } + virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getContained() SLANG_OVERRIDE + { + return m_contained; + } - UnknownCastableAdapter(ISlangUnknown* unk): - m_contained(unk) + UnknownCastableAdapter(ISlangUnknown* unk) + : m_contained(unk) { SLANG_ASSERT(unk); } @@ -171,15 +182,15 @@ protected: struct CastableUtil { - /// Given an ISlangUnkown return as a castable interface. - /// Can use UnknownCastableAdapter if can't queryInterface unk to ICastable + /// Given an ISlangUnkown return as a castable interface. + /// Can use UnknownCastableAdapter if can't queryInterface unk to ICastable static ComPtr getCastable(ISlangUnknown* unk); }; -// A way to clone an interface (that derives from IClonable) such that it returns an interface +// A way to clone an interface (that derives from IClonable) such that it returns an interface // of the same type. -template +template SLANG_FORCE_INLINE ComPtr cloneInterface(T* in) { SLANG_ASSERT(in); diff --git a/source/core/slang-char-encode.cpp b/source/core/slang-char-encode.cpp index 526c6c923..a27e7ba82 100644 --- a/source/core/slang-char-encode.cpp +++ b/source/core/slang-char-encode.cpp @@ -3,20 +3,23 @@ namespace Slang { -class Utf8CharEncoding : public CharEncoding +class Utf8CharEncoding : public CharEncoding { public: typedef CharEncoding Super; - virtual void encode(const UnownedStringSlice& slice, List& ioBuffer) override - { + virtual void encode(const UnownedStringSlice& slice, List& ioBuffer) override + { ioBuffer.addRange((const Byte*)slice.begin(), slice.getLength()); - } - virtual void decode(const Byte* bytes, int length, List& ioChars) override - { + } + virtual void decode(const Byte* bytes, int length, List& ioChars) override + { ioChars.addRange((const char*)bytes, length); - } - Utf8CharEncoding() : Super(CharEncodeType::UTF8) {} + } + Utf8CharEncoding() + : Super(CharEncodeType::UTF8) + { + } }; class Utf32CharEncoding : public CharEncoding @@ -24,93 +27,98 @@ class Utf32CharEncoding : public CharEncoding public: typedef CharEncoding Super; - virtual void encode(const UnownedStringSlice& slice, List& ioBuffer) override - { - Index ptr = 0; - while (ptr < slice.getLength()) - { - const Char32 codePoint = getUnicodePointFromUTF8([&]() -> Byte - { - if (ptr < slice.getLength()) - return slice[ptr++]; - else - return '\0'; - }); + virtual void encode(const UnownedStringSlice& slice, List& ioBuffer) override + { + Index ptr = 0; + while (ptr < slice.getLength()) + { + const Char32 codePoint = getUnicodePointFromUTF8( + [&]() -> Byte + { + if (ptr < slice.getLength()) + return slice[ptr++]; + else + return '\0'; + }); // Note: Assumes byte order is same as arch byte order ioBuffer.addRange((const Byte*)&codePoint, 4); - } - } - virtual void decode(const Byte* bytes, int length, List& ioBuffer) override - { + } + } + virtual void decode(const Byte* bytes, int length, List& ioBuffer) override + { // Note: Assumes bytes is Char32 aligned SLANG_ASSERT((size_t(bytes) & 3) == 0); - const Char32* content = (const Char32*)bytes; - for (int i = 0; i < (length >> 2); i++) - { - char buf[5]; - int count = encodeUnicodePointToUTF8(content[i], buf); + const Char32* content = (const Char32*)bytes; + for (int i = 0; i < (length >> 2); i++) + { + char buf[5]; + int count = encodeUnicodePointToUTF8(content[i], buf); for (int j = 0; j < count; j++) ioBuffer.addRange(buf, count); - } - } + } + } - Utf32CharEncoding() : Super(CharEncodeType::UTF32) {} + Utf32CharEncoding() + : Super(CharEncodeType::UTF32) + { + } }; -class Utf16CharEncoding : public CharEncoding //UTF16 +class Utf16CharEncoding : public CharEncoding // UTF16 { public: typedef CharEncoding Super; - Utf16CharEncoding(bool reverseOrder): - Super(reverseOrder ? CharEncodeType::UTF16Reversed : CharEncodeType::UTF16), - m_reverseOrder(reverseOrder) - {} - virtual void encode(const UnownedStringSlice& slice, List& ioBuffer) override - { - Index index = 0; - while (index < slice.getLength()) - { - const Char32 codePoint = getUnicodePointFromUTF8([&]() -> Byte - { - if (index < slice.getLength()) - return slice[index++]; - else - return '\0'; - }); - - Char16 buffer[2]; - int count; - if (!m_reverseOrder) - count = encodeUnicodePointToUTF16(codePoint, buffer); - else - count = encodeUnicodePointToUTF16Reversed(codePoint, buffer); + Utf16CharEncoding(bool reverseOrder) + : Super(reverseOrder ? CharEncodeType::UTF16Reversed : CharEncodeType::UTF16) + , m_reverseOrder(reverseOrder) + { + } + virtual void encode(const UnownedStringSlice& slice, List& ioBuffer) override + { + Index index = 0; + while (index < slice.getLength()) + { + const Char32 codePoint = getUnicodePointFromUTF8( + [&]() -> Byte + { + if (index < slice.getLength()) + return slice[index++]; + else + return '\0'; + }); + + Char16 buffer[2]; + int count; + if (!m_reverseOrder) + count = encodeUnicodePointToUTF16(codePoint, buffer); + else + count = encodeUnicodePointToUTF16Reversed(codePoint, buffer); ioBuffer.addRange((const Byte*)buffer, count * 2); - } - } - virtual void decode(const Byte* bytes, int length, List& ioBuffer) override - { - Index index = 0; - while (index < length) - { - auto readByte = [&]() -> Byte - { - return (index < length) ? bytes[index++] : Byte(0); - }; - const Char32 codePoint = m_reverseOrder ? - getUnicodePointFromUTF16Reversed(readByte) : - getUnicodePointFromUTF16(readByte); - - char buf[5]; - int count = encodeUnicodePointToUTF8(codePoint, buf); - ioBuffer.addRange((const char*)buf, count); - } - } + } + } + virtual void decode(const Byte* bytes, int length, List& ioBuffer) override + { + Index index = 0; + while (index < length) + { + auto readByte = [&]() -> Byte { return (index < length) ? bytes[index++] : Byte(0); }; + const Char32 codePoint = m_reverseOrder ? getUnicodePointFromUTF16Reversed(readByte) + : getUnicodePointFromUTF16(readByte); + + char buf[5]; + int count = encodeUnicodePointToUTF8(codePoint, buf); + ioBuffer.addRange((const char*)buf, count); + } + } private: bool m_reverseOrder = false; }; -/* static */CharEncodeType CharEncoding::determineEncoding(const Byte* bytes, size_t bytesCount, size_t& outOffset) +/* static */ CharEncodeType CharEncoding::determineEncoding( + const Byte* bytes, + size_t bytesCount, + size_t& outOffset) { // TODO(JS): Assumes the bytes are suitably aligned @@ -137,7 +145,7 @@ private: // If we don't have a 'mark' byte then we are bit stumped. We'll look for // null (non-terminator) bytes and assume they mean we have a 16-bit encoding - for(size_t i = 0; i < (bytesCount-1); i += 2) + for (size_t i = 0; i < (bytesCount - 1); i += 2) { #if SLANG_LITTLE_ENDIAN const auto low = bytes[i]; @@ -164,41 +172,42 @@ static Utf16CharEncoding _utf16Encoding(false); static Utf16CharEncoding _utf16EncodingReversed(true); static Utf32CharEncoding _utf32Encoding; -/* static */CharEncoding* const CharEncoding::g_encoding[Index(CharEncodeType::CountOf)] -{ - &_utf8Encoding, // UTF8, - &_utf16Encoding, // UTF16, - &_utf16EncodingReversed, // UTF16Reversed, - &_utf32Encoding, // UTF32, +/* static */ CharEncoding* const CharEncoding::g_encoding[Index(CharEncodeType::CountOf)]{ + &_utf8Encoding, // UTF8, + &_utf16Encoding, // UTF16, + &_utf16EncodingReversed, // UTF16Reversed, + &_utf32Encoding, // UTF32, }; CharEncoding* CharEncoding::UTF8 = &_utf8Encoding; CharEncoding* CharEncoding::UTF16 = &_utf16Encoding; CharEncoding* CharEncoding::UTF16Reversed = &_utf16EncodingReversed; CharEncoding* CharEncoding::UTF32 = &_utf32Encoding; - + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! UTF8Util !!!!!!!!!!!!!!!!!!!!!!!!! */ -/* static */Index UTF8Util::calcCodePointCount(const UnownedStringSlice& in) +/* static */ Index UTF8Util::calcCodePointCount(const UnownedStringSlice& in) { Index count = 0; // Analyse with bytes... const int8_t* cur = (const int8_t*)in.begin(); - const int8_t*const end = (const int8_t*)in.end(); + const int8_t* const end = (const int8_t*)in.end(); while (cur < end) { const auto c = *cur++; - + count++; // If c < 0 it means the top bit is set... which means we have multiple bytes if (c < 0) { // https://en.wikipedia.org/wiki/UTF-8 - // All continuation bytes contain exactly six bits from the code point.So the next six bits of the code point - /// are stored in the low order six bits of the next byte, and 10 is stored in the high order two bits to + // All continuation bytes contain exactly six bits from the code point.So the next six + // bits of the code point + /// are stored in the low order six bits of the next byte, and 10 is stored in the high + /// order two bits to // mark it as a continuation byte(so 10000010). while (cur < end && (*cur & 0xc0) == 0x80) @@ -217,7 +226,8 @@ Index UTF8Util::calcUTF16CharCount(const UnownedStringSlice& in) Index readPtr = 0; for (;;) { - int c = getUnicodePointFromUTF8([&]() -> Byte + int c = getUnicodePointFromUTF8( + [&]() -> Byte { if (readPtr < in.getLength()) return in[readPtr++]; diff --git a/source/core/slang-char-encode.h b/source/core/slang-char-encode.h index a7cd501ab..74968a6ab 100644 --- a/source/core/slang-char-encode.h +++ b/source/core/slang-char-encode.h @@ -1,13 +1,13 @@ #ifndef SLANG_CORE_CHAR_ENCODE_H #define SLANG_CORE_CHAR_ENCODE_H -#include "slang-secure-crt.h" #include "slang-basic.h" +#include "slang-secure-crt.h" namespace Slang { -// NOTE! Order must be kept the same to match up with +// NOTE! Order must be kept the same to match up with enum class CharEncodeType { UTF8, @@ -17,7 +17,7 @@ enum class CharEncodeType CountOf, }; -template +template Char32 getUnicodePointFromUTF8(const ReadByteFunc& readByte) { Char32 codePoint = 0; @@ -38,7 +38,7 @@ Char32 getUnicodePointFromUTF8(const ReadByteFunc& readByte) return codePoint; } -template +template Char32 getUnicodePointFromUTF16(const ReadByteFunc& readByte) { uint32_t byte0 = Byte(readByte()); @@ -55,7 +55,7 @@ Char32 getUnicodePointFromUTF16(const ReadByteFunc& readByte) return Char32(word0); } -template +template Char32 getUnicodePointFromUTF16Reversed(const ReadByteFunc& readByte) { uint32_t byte0 = Byte(readByte()); @@ -72,7 +72,7 @@ Char32 getUnicodePointFromUTF16Reversed(const ReadByteFunc& readByte) return Char32(word0); } -template +template Char32 getUnicodePointFromUTF32(const ReadByteFunc& readByte) { uint32_t byte0 = Byte(readByte()); @@ -163,52 +163,55 @@ static const Char16 kUTF16ReversedHeader = 0xFFFE; class CharEncoding { public: - static CharEncoding* UTF8,* UTF16,* UTF16Reversed,* UTF32; + static CharEncoding *UTF8, *UTF16, *UTF16Reversed, *UTF32; - /// Encode Utf8 held in slice append into ioBuffer + /// Encode Utf8 held in slice append into ioBuffer virtual void encode(const UnownedStringSlice& str, List& ioBuffer) = 0; - /// Decode buffer into Utf8 held in ioBuffer + /// Decode buffer into Utf8 held in ioBuffer virtual void decode(const Byte* buffer, int length, List& ioBuffer) = 0; - virtual ~CharEncoding() {} + virtual ~CharEncoding() {} - /// Get the encoding type + /// Get the encoding type CharEncodeType getEncodingType() const { return m_encodingType; } - /// Given some bytes determines a character encoding type, based on the initial bytes. - /// If can't be determined will assume UTF8. - /// Outputs the offset to the first non mark in outOffset - static CharEncodeType determineEncoding(const Byte* bytes, size_t bytesCount, size_t& outOffset); + /// Given some bytes determines a character encoding type, based on the initial bytes. + /// If can't be determined will assume UTF8. + /// Outputs the offset to the first non mark in outOffset + static CharEncodeType determineEncoding( + const Byte* bytes, + size_t bytesCount, + size_t& outOffset); - /// Get the + /// Get the static CharEncoding* getEncoding(CharEncodeType type) { return g_encoding[Index(type)]; } - CharEncoding(CharEncodeType encodingType) : - m_encodingType(encodingType) + CharEncoding(CharEncodeType encodingType) + : m_encodingType(encodingType) { } protected: - CharEncodeType m_encodingType; - static CharEncoding*const g_encoding[Index(CharEncodeType::CountOf)]; + static CharEncoding* const g_encoding[Index(CharEncodeType::CountOf)]; }; struct UTF8Util { - /// Given a slice calculate the number of code points (unicode chars) - /// - /// NOTE! This doesn't check the *validity* of code points/encoding. - /// Non valid utf8 input or ending starting in partial characters, will produce - /// undefined results without error. + /// Given a slice calculate the number of code points (unicode chars) + /// + /// NOTE! This doesn't check the *validity* of code points/encoding. + /// Non valid utf8 input or ending starting in partial characters, will produce + /// undefined results without error. static Index calcCodePointCount(const UnownedStringSlice& in); - /// Given a slice in UTF8, calculate the number of UTF16 characters needed to represent the string. + /// Given a slice in UTF8, calculate the number of UTF16 characters needed to represent the + /// string. static Index calcUTF16CharCount(const UnownedStringSlice& in); }; -} +} // namespace Slang #endif diff --git a/source/core/slang-char-util.cpp b/source/core/slang-char-util.cpp index ea9e6dbf2..f9c61ec03 100644 --- a/source/core/slang-char-util.cpp +++ b/source/core/slang-char-util.cpp @@ -1,8 +1,9 @@ #include "slang-char-util.h" -namespace Slang { +namespace Slang +{ -/* static */CharUtil::CharFlagMap CharUtil::makeCharFlagMap() +/* static */ CharUtil::CharFlagMap CharUtil::makeCharFlagMap() { CharUtil::CharFlagMap map; memset(&map, 0, sizeof(map)); @@ -46,11 +47,11 @@ namespace Slang { return map; } -/* static */int CharUtil::_ensureLink() +/* static */ int CharUtil::_ensureLink() { return makeCharFlagMap().flags[0]; } -/* static */const CharUtil::CharFlagMap CharUtil::g_charFlagMap = makeCharFlagMap(); +/* static */ const CharUtil::CharFlagMap CharUtil::g_charFlagMap = makeCharFlagMap(); } // namespace Slang diff --git a/source/core/slang-char-util.h b/source/core/slang-char-util.h index 88af24426..896eb6956 100644 --- a/source/core/slang-char-util.h +++ b/source/core/slang-char-util.h @@ -3,7 +3,8 @@ #include "slang-string.h" -namespace Slang { +namespace Slang +{ struct CharUtil { @@ -12,12 +13,13 @@ struct CharUtil { enum Enum : Flags { - Upper = 0x01, ///< A-Z - Lower = 0x02, ///< a-z - Digit = 0x04, ///< 0-9 - HorizontalWhitespace = 0x08, ///< Whitespace that can appear horizontally (ie excluding CR/LF) - HexDigit = 0x10, ///< 0-9, a-f, A-F - VerticalWhitespace = 0x20, ///< \n \r + Upper = 0x01, ///< A-Z + Lower = 0x02, ///< a-z + Digit = 0x04, ///< 0-9 + HorizontalWhitespace = + 0x08, ///< Whitespace that can appear horizontally (ie excluding CR/LF) + HexDigit = 0x10, ///< 0-9, a-f, A-F + VerticalWhitespace = 0x20, ///< \n \r }; }; @@ -26,40 +28,62 @@ struct CharUtil SLANG_FORCE_INLINE static bool isUpper(char c) { return c >= 'A' && c <= 'Z'; } SLANG_FORCE_INLINE static bool isHorizontalWhitespace(char c) { return c == ' ' || c == '\t'; } SLANG_FORCE_INLINE static bool isVerticalWhitespace(char c) { return c == '\n' || c == '\r'; } - SLANG_FORCE_INLINE static bool isWhitespace(char c) { return (getFlags(c) & (Flag::HorizontalWhitespace | Flag::VerticalWhitespace)) != 0; } + SLANG_FORCE_INLINE static bool isWhitespace(char c) + { + return (getFlags(c) & (Flag::HorizontalWhitespace | Flag::VerticalWhitespace)) != 0; + } - /// True if it's alpha - SLANG_FORCE_INLINE static bool isAlpha(char c) { return (getFlags(c) & (Flag::Upper | Flag::Lower)) != 0; } - /// True if it's alpha or a digit - SLANG_FORCE_INLINE static bool isAlphaOrDigit(char c) { return (getFlags(c) & (Flag::Upper | Flag::Lower | Flag::Digit)) != 0; } + /// True if it's alpha + SLANG_FORCE_INLINE static bool isAlpha(char c) + { + return (getFlags(c) & (Flag::Upper | Flag::Lower)) != 0; + } + /// True if it's alpha or a digit + SLANG_FORCE_INLINE static bool isAlphaOrDigit(char c) + { + return (getFlags(c) & (Flag::Upper | Flag::Lower | Flag::Digit)) != 0; + } - /// True if the character is a valid hex character - SLANG_FORCE_INLINE static bool isHexDigit(char c) { return (getFlags(c) & Flag::HexDigit) != 0; } + /// True if the character is a valid hex character + SLANG_FORCE_INLINE static bool isHexDigit(char c) + { + return (getFlags(c) & Flag::HexDigit) != 0; + } - /// True if the character is an octal digit + /// True if the character is an octal digit SLANG_FORCE_INLINE static bool isOctalDigit(char c) { return c >= '0' && c <= '7'; } - /// For a given character get the associated flags + /// For a given character get the associated flags SLANG_FORCE_INLINE static Flags getFlags(char c) { return g_charFlagMap.flags[size_t(c)]; } - /// Given a character return the lower case equivalent - SLANG_FORCE_INLINE static char toLower(char c) { return (c >= 'A' && c <= 'Z') ? (c -'A' + 'a') : c; } - /// Given a character return the upper case equivalent - SLANG_FORCE_INLINE static char toUpper(char c) { return (c >= 'a' && c <= 'z') ? (c -'a' + 'A') : c; } + /// Given a character return the lower case equivalent + SLANG_FORCE_INLINE static char toLower(char c) + { + return (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; + } + /// Given a character return the upper case equivalent + SLANG_FORCE_INLINE static char toUpper(char c) + { + return (c >= 'a' && c <= 'z') ? (c - 'a' + 'A') : c; + } - /// Given a value between 0-15 inclusive returns the hex digit. Uses lower case hex. - SLANG_FORCE_INLINE static char getHexChar(Index i) { SLANG_ASSERT((i & ~Index(0xf)) == 0); return char(i >= 10 ? (i - 10 + 'a') : (i + '0')); } + /// Given a value between 0-15 inclusive returns the hex digit. Uses lower case hex. + SLANG_FORCE_INLINE static char getHexChar(Index i) + { + SLANG_ASSERT((i & ~Index(0xf)) == 0); + return char(i >= 10 ? (i - 10 + 'a') : (i + '0')); + } - /// Returns the value if c interpretted as a decimal digit - /// If c is not a valid digit returns -1 + /// Returns the value if c interpretted as a decimal digit + /// If c is not a valid digit returns -1 inline static int getDecimalDigitValue(char c) { return isDigit(c) ? (c - '0') : -1; } - /// Returns the value if c interpretted as a hex digit - /// If c is not a valid hex returns -1 + /// Returns the value if c interpretted as a hex digit + /// If c is not a valid hex returns -1 inline static int getHexDigitValue(char c); - - /// Returns the value if c interpretted as a octal digit - /// If c is not a valid octal returns -1 + + /// Returns the value if c interpretted as a octal digit + /// If c is not a valid octal returns -1 inline static int getOctalDigitValue(char c) { return isOctalDigit(c) ? (c - '0') : -1; } struct CharFlagMap @@ -69,16 +93,17 @@ struct CharUtil static CharFlagMap makeCharFlagMap(); - // HACK! - // JS: Many of the inlined functions of CharUtil just access a global map. That referencing this global is *NOT* enough to - // link correctly with CharUtil on linux for a shared library. Caling this function can force linkage. + // HACK! + // JS: Many of the inlined functions of CharUtil just access a global map. That referencing this + // global is *NOT* enough to link correctly with CharUtil on linux for a shared library. Caling + // this function can force linkage. static int _ensureLink(); static const CharFlagMap g_charFlagMap; }; - + // ------------------------------------------------------------------------------------ -inline /* static */int CharUtil::getHexDigitValue(char c) +inline /* static */ int CharUtil::getHexDigitValue(char c) { if (c >= '0' && c <= '9') { diff --git a/source/core/slang-chunked-list.h b/source/core/slang-chunked-list.h index d414eaefb..95324f8c9 100644 --- a/source/core/slang-chunked-list.h +++ b/source/core/slang-chunked-list.h @@ -1,16 +1,15 @@ #ifndef SLANG_CORE_CHUNKED_LIST_H #define SLANG_CORE_CHUNKED_LIST_H -#include "slang.h" - #include "slang-allocator.h" #include "slang-array-view.h" #include "slang-math.h" +#include "slang.h" namespace Slang { // Items stored in a ChunkedList are guaranteed to have fixed address. -template +template class ChunkedList { private: @@ -21,10 +20,7 @@ private: uint32_t size = 0; uint32_t capacity = defaultChunkSize; Chunk* next = nullptr; - T* begin() - { - return reinterpret_cast(this + 1); - } + T* begin() { return reinterpret_cast(this + 1); } T* end() { return begin() + size; } }; @@ -60,24 +56,26 @@ private: public: typedef ChunkedList ThisType; ChunkedList() - : m_lastChunk(&m_firstChunk) - , m_count(0) - {} - template ChunkedList(const T& val, Args... args) { _init(val, args...); } + : m_lastChunk(&m_firstChunk), m_count(0) + { + } + template + ChunkedList(const T& val, Args... args) + { + _init(val, args...); + } ChunkedList(const ThisType& list) - : m_lastChunk(&m_firstChunk) - , m_count(0) + : m_lastChunk(&m_firstChunk), m_count(0) { this->operator=(list); } ChunkedList(ThisType&& list) - : m_lastChunk(&m_firstChunk) - , m_count(0) + : m_lastChunk(&m_firstChunk), m_count(0) { this->operator=(static_cast(list)); } ~ChunkedList() { _deallocateBuffer(); } - template + template ThisType& operator=(const ChunkedList& list) { clearAndDeallocate(); @@ -213,7 +211,8 @@ public: return result; } - template T* addRange(const TContainer& list) + template + T* addRange(const TContainer& list) { Chunk* chunk = _maybeReserveForAdd((uint32_t)list.getCount()); auto result = chunk->begin() + chunk->size; @@ -235,7 +234,6 @@ public: } private: - Index m_count = 0; ///< The amount of elements FirstChunk m_firstChunk; Chunk* m_lastChunk = &m_firstChunk; @@ -262,7 +260,8 @@ private: return AllocateMethod::deallocateArray(ptr, count); } - template void _init(const T& val, Args... args) + template + void _init(const T& val, Args... args) { add(val); _init(args...); diff --git a/source/core/slang-com-object.h b/source/core/slang-com-object.h index 617b7ccca..801af61a4 100644 --- a/source/core/slang-com-object.h +++ b/source/core/slang-com-object.h @@ -2,34 +2,35 @@ #define SLANG_COM_OBJECT_H #include "slang-basic.h" + #include namespace Slang { -/// A base class for COM interfaces that require atomic ref counting +/// A base class for COM interfaces that require atomic ref counting /// and are *NOT* derived from RefObject class ComBaseObject { public: - - /// If assigned the the ref count is *NOT* copied + /// If assigned the the ref count is *NOT* copied ComBaseObject& operator=(const ComBaseObject&) { return *this; } - /// Copy Ctor, does not copy ref count - ComBaseObject(const ComBaseObject&) : - m_refCount(0) - {} + /// Copy Ctor, does not copy ref count + ComBaseObject(const ComBaseObject&) + : m_refCount(0) + { + } - /// Default Ctor sets with no refs + /// Default Ctor sets with no refs ComBaseObject() : m_refCount(0) - {} + { + } - /// Dtor needs to be virtual to avoid needing to - /// Implement release for all derived types. - virtual ~ComBaseObject() - {} + /// Dtor needs to be virtual to avoid needing to + /// Implement release for all derived types. + virtual ~ComBaseObject() {} protected: inline uint32_t _releaseImpl(); @@ -50,7 +51,7 @@ inline uint32_t ComBaseObject::_releaseImpl() return count; } -#define SLANG_COM_BASE_IUNKNOWN_QUERY_INTERFACE \ +#define SLANG_COM_BASE_IUNKNOWN_QUERY_INTERFACE \ SLANG_NO_THROW SlangResult SLANG_MCALL queryInterface(SlangUUID const& uuid, void** outObject) \ SLANG_OVERRIDE \ { \ @@ -63,10 +64,16 @@ inline uint32_t ComBaseObject::_releaseImpl() } \ return SLANG_E_NO_INTERFACE; \ } -#define SLANG_COM_BASE_IUNKNOWN_ADD_REF \ - SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return ++m_refCount; } -#define SLANG_COM_BASE_IUNKNOWN_RELEASE \ - SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return _releaseImpl(); } +#define SLANG_COM_BASE_IUNKNOWN_ADD_REF \ + SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE \ + { \ + return ++m_refCount; \ + } +#define SLANG_COM_BASE_IUNKNOWN_RELEASE \ + SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE \ + { \ + return _releaseImpl(); \ + } #define SLANG_COM_BASE_IUNKNOWN_ALL \ SLANG_COM_BASE_IUNKNOWN_QUERY_INTERFACE \ SLANG_COM_BASE_IUNKNOWN_ADD_REF \ @@ -82,11 +89,12 @@ protected: public: ComObject() : comRefCount(0) - {} - ComObject(const ComObject& rhs) : - RefObject(rhs), - comRefCount(0) - {} + { + } + ComObject(const ComObject& rhs) + : RefObject(rhs), comRefCount(0) + { + } ComObject& operator=(const ComObject&) { return *this; } @@ -125,10 +133,16 @@ public: } \ return SLANG_E_NO_INTERFACE; \ } -#define SLANG_COM_OBJECT_IUNKNOWN_ADD_REF \ - SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE { return addRefImpl(); } -#define SLANG_COM_OBJECT_IUNKNOWN_RELEASE \ - SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE { return releaseImpl(); } +#define SLANG_COM_OBJECT_IUNKNOWN_ADD_REF \ + SLANG_NO_THROW uint32_t SLANG_MCALL addRef() SLANG_OVERRIDE \ + { \ + return addRefImpl(); \ + } +#define SLANG_COM_OBJECT_IUNKNOWN_RELEASE \ + SLANG_NO_THROW uint32_t SLANG_MCALL release() SLANG_OVERRIDE \ + { \ + return releaseImpl(); \ + } #define SLANG_COM_OBJECT_IUNKNOWN_ALL \ SLANG_COM_OBJECT_IUNKNOWN_QUERY_INTERFACE \ SLANG_COM_OBJECT_IUNKNOWN_ADD_REF \ diff --git a/source/core/slang-command-line.cpp b/source/core/slang-command-line.cpp index bfd9ed11a..8269d37c5 100644 --- a/source/core/slang-command-line.cpp +++ b/source/core/slang-command-line.cpp @@ -1,17 +1,17 @@ // slang-command-line.cpp #include "slang-command-line.h" +#include "slang-com-helper.h" #include "slang-process.h" - -#include "slang-string.h" #include "slang-string-escape-util.h" #include "slang-string-util.h" +#include "slang-string.h" -#include "slang-com-helper.h" - -namespace Slang { +namespace Slang +{ -/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ExecutableLocation !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ExecutableLocation !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + */ void ExecutableLocation::set(const String& dir, const String& name) { diff --git a/source/core/slang-command-line.h b/source/core/slang-command-line.h index 163daf710..804266ad1 100644 --- a/source/core/slang-command-line.h +++ b/source/core/slang-command-line.h @@ -2,10 +2,11 @@ #ifndef SLANG_COMMAND_LINE_H #define SLANG_COMMAND_LINE_H -#include "slang-string.h" #include "slang-list.h" +#include "slang-string.h" -namespace Slang { +namespace Slang +{ struct ExecutableLocation { @@ -13,43 +14,67 @@ struct ExecutableLocation enum Type { - Unknown, ///< Not specified - Path, ///< The executable is set as a path (ie won't be searched for) - Name, ///< The executable is passed as a name which will be searched for + Unknown, ///< Not specified + Path, ///< The executable is set as a path (ie won't be searched for) + Name, ///< The executable is passed as a name which will be searched for }; - /// Set the executable path. - /// NOTE! On some targets the executable path *must* include an extension to be able to start as a process - void setPath(const String& path) { m_type = Type::Path; m_pathOrName = path; } + /// Set the executable path. + /// NOTE! On some targets the executable path *must* include an extension to be able to start as + /// a process + void setPath(const String& path) + { + m_type = Type::Path; + m_pathOrName = path; + } - /// Set a filename (such that the path will be looked up) - void setName(const String& filename) { m_type = Type::Name; m_pathOrName = filename; } + /// Set a filename (such that the path will be looked up) + void setName(const String& filename) + { + m_type = Type::Name; + m_pathOrName = filename; + } - void set(Type type, const String& pathOrName) { m_type = type; m_pathOrName = pathOrName; } + void set(Type type, const String& pathOrName) + { + m_type = type; + m_pathOrName = pathOrName; + } - /// Set the executable path from a base directory and an executable name (no suffix such as '.exe' needed) + /// Set the executable path from a base directory and an executable name (no suffix such as + /// '.exe' needed) void set(const String& dir, const String& name); - /// Determines if it's a name or a path when it sets + /// Determines if it's a name or a path when it sets void set(const String& nameOrPath); - /// Append as text to out. + /// Append as text to out. void append(StringBuilder& out) const; - /// Reset state to be same as ctor - void reset() { m_type = Type::Unknown; m_pathOrName = String(); } + /// Reset state to be same as ctor + void reset() + { + m_type = Type::Unknown; + m_pathOrName = String(); + } - /// Equality means exactly the same definition. - /// *NOT* that exactly the same executable is specified - bool operator==(const ThisType& rhs) const { return m_type == rhs.m_type && m_pathOrName == rhs.m_pathOrName; } + /// Equality means exactly the same definition. + /// *NOT* that exactly the same executable is specified + bool operator==(const ThisType& rhs) const + { + return m_type == rhs.m_type && m_pathOrName == rhs.m_pathOrName; + } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } ExecutableLocation() {} - ExecutableLocation(const String& dir, const String& name) { set(dir, name); } - ExecutableLocation(Type type, const String& pathOrName) : m_type(type), m_pathOrName(pathOrName) {} + ExecutableLocation(const String& dir, const String& name) { set(dir, name); } + ExecutableLocation(Type type, const String& pathOrName) + : m_type(type), m_pathOrName(pathOrName) + { + } explicit ExecutableLocation(const String& nameOrPath) { set(nameOrPath); } - + Type m_type = Type::Unknown; String m_pathOrName; }; @@ -58,42 +83,52 @@ struct CommandLine { typedef CommandLine ThisType; - /// Add args - assumed unescaped + /// Add args - assumed unescaped void addArg(const String& in) { m_args.add(in); } - void addArgs(const String* args, Int argsCount) { for (Int i = 0; i < argsCount; ++i) addArg(args[i]); } + void addArgs(const String* args, Int argsCount) + { + for (Int i = 0; i < argsCount; ++i) + addArg(args[i]); + } void addArgIfNotFound(const String& in); - /// Find the index of an arg which is exact match for slice - SLANG_INLINE Index findArgIndex(const UnownedStringSlice& slice) const { return m_args.indexOf(slice); } + /// Find the index of an arg which is exact match for slice + SLANG_INLINE Index findArgIndex(const UnownedStringSlice& slice) const + { + return m_args.indexOf(slice); + } - /// For handling args where the switch is placed directly in front of the path - void addPrefixPathArg(const char* prefix, const String& path, const char* pathPostfix = nullptr); + /// For handling args where the switch is placed directly in front of the path + void addPrefixPathArg( + const char* prefix, + const String& path, + const char* pathPostfix = nullptr); - /// Get the total number of args + /// Get the total number of args SLANG_FORCE_INLINE Index getArgCount() const { return m_args.getCount(); } - /// Reset to the initial state - void reset() { *this = CommandLine(); } + /// Reset to the initial state + void reset() { *this = CommandLine(); } - /// Append the args + /// Append the args void appendArgs(StringBuilder& out) const; - /// Append the command line to out + /// Append the command line to out void append(StringBuilder& out) const; - /// convert into a string + /// convert into a string String toString() const; - /// Convert just the args to string + /// Convert just the args to string String toStringArgs() const; - /// Set an executable location + /// Set an executable location void setExecutableLocation(const ExecutableLocation& loc) { m_executableLocation = loc; } - ExecutableLocation m_executableLocation; ///< The executable location - List m_args; ///< The arguments (Stored *unescaped*) + ExecutableLocation m_executableLocation; ///< The executable location + List m_args; ///< The arguments (Stored *unescaped*) }; -} +} // namespace Slang #endif // SLANG_COMMAND_LINE_H diff --git a/source/core/slang-command-options-writer.cpp b/source/core/slang-command-options-writer.cpp index afa46db64..f46bcc56c 100644 --- a/source/core/slang-command-options-writer.cpp +++ b/source/core/slang-command-options-writer.cpp @@ -2,18 +2,26 @@ #include "slang-command-options-writer.h" -#include "slang-string-util.h" -#include "slang-char-util.h" #include "slang-byte-encode-util.h" +#include "slang-char-util.h" +#include "slang-string-util.h" + +namespace Slang +{ -namespace Slang { - -namespace { // anonymous +namespace +{ // anonymous typedef CommandOptionsWriter::Style Style; -} // anonymous +} // namespace -static bool _isMarkdown(Style style) { return style == Style::Markdown || style == Style::NoLinkMarkdown; } -static bool _hasLinks(Style style) { return style == Style::Markdown; } +static bool _isMarkdown(Style style) +{ + return style == Style::Markdown || style == Style::NoLinkMarkdown; +} +static bool _hasLinks(Style style) +{ + return style == Style::Markdown; +} /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! MarkdownCommandOptionsWriter !!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -25,17 +33,17 @@ public: typedef uint32_t LinkFlags; struct LinkFlag { - enum Enum + enum Enum { Category = 0x1, - Option = 0x2, + Option = 0x2, All = Category | Option, }; }; - MarkdownCommandOptionsWriter(const Options& options): - Super(options) + MarkdownCommandOptionsWriter(const Options& options) + : Super(options) { } @@ -45,15 +53,17 @@ protected: virtual void appendDescriptionImpl() SLANG_OVERRIDE; void _appendParagraph(const UnownedStringSlice& text, LinkFlags flags = LinkFlag::All); - void _appendParagraph(const ConstArrayView& words, LinkFlags flags = LinkFlag::All); + void _appendParagraph( + const ConstArrayView& words, + LinkFlags flags = LinkFlag::All); - void _appendMaybeLink(const UnownedStringSlice& word, LinkFlags linkFlags); + void _appendMaybeLink(const UnownedStringSlice& word, LinkFlags linkFlags); void _appendText(const UnownedStringSlice& text); void _appendDescriptionForCategory(Index categoryIndex); UnownedStringSlice _getLinkName(CommandOptions::LookupKind kind, Index index); UnownedStringSlice _getLinkName(const NameKey& key, Index index); - + void _appendQuickLinks(); bool m_hasLinks = false; @@ -91,15 +101,15 @@ static bool _needsMarkdownEscape(const UnownedStringSlice& text) { switch (c) { - case '<': - case '>': - case '&': - case '[': - case ']': + case '<': + case '>': + case '&': + case '[': + case ']': { return true; } - default: break; + default: break; } } @@ -115,12 +125,12 @@ void _appendEscapedMarkdown(const UnownedStringSlice& text, StringBuilder& ioBuf { switch (c) { - case '<': ioBuf << "<"; break; - case '>': ioBuf << ">"; break; - case '&': ioBuf << "&"; break; - case '[': ioBuf << "\\["; break; - case ']': ioBuf << "\\]"; break; - default: ioBuf << c; + case '<': ioBuf << "<"; break; + case '>': ioBuf << ">"; break; + case '&': ioBuf << "&"; break; + case '[': ioBuf << "\\["; break; + case ']': ioBuf << "\\]"; break; + default: ioBuf << c; } } } @@ -149,7 +159,9 @@ void MarkdownCommandOptionsWriter::_appendQuickLinks() m_builder << "\n"; } -void MarkdownCommandOptionsWriter::_appendParagraph(const UnownedStringSlice& text, LinkFlags linkFlags) +void MarkdownCommandOptionsWriter::_appendParagraph( + const UnownedStringSlice& text, + LinkFlags linkFlags) { List words; StringUtil::splitOnWhitespace(text, words); @@ -171,12 +183,16 @@ static UnownedStringSlice _trimPunctuation(const UnownedStringSlice& word) const char* start = word.begin(); const char* end = word.end(); - while (start < end && _isStartPunctionation(*start)) start++; - while (end > start && _isEndPunctionation(end[-1])) --end; + while (start < end && _isStartPunctionation(*start)) + start++; + while (end > start && _isEndPunctionation(end[-1])) + --end; return UnownedStringSlice(start, end); } -void MarkdownCommandOptionsWriter::_appendMaybeLink(const UnownedStringSlice& inWord, LinkFlags linkFlags) +void MarkdownCommandOptionsWriter::_appendMaybeLink( + const UnownedStringSlice& inWord, + LinkFlags linkFlags) { if (linkFlags) { @@ -190,17 +206,27 @@ void MarkdownCommandOptionsWriter::_appendMaybeLink(const UnownedStringSlice& in // Look for options if (trimmedWord[0] == '-' && (linkFlags & LinkFlag::Option)) { - index = m_commandOptions->findTargetIndexByName(LookupKind::Option, trimmedWord, &nameKey); + index = m_commandOptions->findTargetIndexByName( + LookupKind::Option, + trimmedWord, + &nameKey); } - else if (trimmedWord[0] == '<' && trimmedWord[trimmedWord.getLength() - 1] == '>' && (linkFlags & LinkFlag::Category)) + else if ( + trimmedWord[0] == '<' && trimmedWord[trimmedWord.getLength() - 1] == '>' && + (linkFlags & LinkFlag::Category)) { - index = m_commandOptions->findTargetIndexByName(LookupKind::Category, trimmedWord.subString(1, trimmedWord.getLength() - 2), &nameKey); + index = m_commandOptions->findTargetIndexByName( + LookupKind::Category, + trimmedWord.subString(1, trimmedWord.getLength() - 2), + &nameKey); } - + if (index > 0) { // Append before the link - _appendEscapedMarkdown(UnownedStringSlice(inWord.begin(), trimmedWord.begin()), m_builder); + _appendEscapedMarkdown( + UnownedStringSlice(inWord.begin(), trimmedWord.begin()), + m_builder); // Make into a link m_builder << "["; @@ -208,7 +234,9 @@ void MarkdownCommandOptionsWriter::_appendMaybeLink(const UnownedStringSlice& in m_builder << "](#" << _getLinkName(nameKey, index) << ")"; // Append after the link - _appendEscapedMarkdown(UnownedStringSlice(trimmedWord.end(), inWord.end()), m_builder); + _appendEscapedMarkdown( + UnownedStringSlice(trimmedWord.end(), inWord.end()), + m_builder); return; } } @@ -217,7 +245,9 @@ void MarkdownCommandOptionsWriter::_appendMaybeLink(const UnownedStringSlice& in _appendEscapedMarkdown(inWord, m_builder); } -void MarkdownCommandOptionsWriter::_appendParagraph(const ConstArrayView& words, LinkFlags linkFlags) +void MarkdownCommandOptionsWriter::_appendParagraph( + const ConstArrayView& words, + LinkFlags linkFlags) { if (m_hasLinks && linkFlags) { @@ -271,19 +301,21 @@ void MarkdownCommandOptionsWriter::_appendDescriptionForCategory(Index categoryI if (m_hasLinks) { // Output anchor - m_builder << "\n"; + m_builder << "\n"; } m_builder << "# " << category.name << "\n\n"; - + // If there is a description output, making \n split paragraphs if (category.description.getLength() > 0) { _appendText(category.description); - } + } } - for (Index optionIndex = category.optionStartIndex; optionIndex < category.optionEndIndex; ++optionIndex) + for (Index optionIndex = category.optionStartIndex; optionIndex < category.optionEndIndex; + ++optionIndex) { const auto& option = options.getOptionAt(optionIndex); @@ -294,7 +326,7 @@ void MarkdownCommandOptionsWriter::_appendDescriptionForCategory(Index categoryI if (isValue) { m_builder << "* "; - // Output all the names + // Output all the names m_builder << "`"; StringUtil::join(names.getBuffer(), names.getCount(), toSlice("`, `"), m_builder); m_builder << "` "; @@ -303,7 +335,8 @@ void MarkdownCommandOptionsWriter::_appendDescriptionForCategory(Index categoryI { if (m_hasLinks) { - m_builder << "\n"; + m_builder << "\n"; } m_builder << "## "; @@ -322,17 +355,24 @@ void MarkdownCommandOptionsWriter::_appendDescriptionForCategory(Index categoryI const char* cur = option.usage.begin(); for (auto usedCategory : usedCategories) { - _appendEscapedMarkdown(UnownedStringSlice(cur, usedCategory.begin()), m_builder); + _appendEscapedMarkdown( + UnownedStringSlice(cur, usedCategory.begin()), + m_builder); // Now do the link - const Index usedCategoryIndex = options.findCategoryByName(usedCategory); + const Index usedCategoryIndex = + options.findCategoryByName(usedCategory); - m_builder << "[" << usedCategory << "](#" << _getLinkName(LookupKind::Category, usedCategoryIndex) << ")"; + m_builder << "[" << usedCategory << "](#" + << _getLinkName(LookupKind::Category, usedCategoryIndex) + << ")"; cur = usedCategory.end(); } - _appendEscapedMarkdown(UnownedStringSlice(cur, option.usage.end()), m_builder); + _appendEscapedMarkdown( + UnownedStringSlice(cur, option.usage.end()), + m_builder); } else { @@ -370,9 +410,9 @@ UnownedStringSlice MarkdownCommandOptionsWriter::_getLinkName(const NameKey& key return m_pool.getSlice(*ptr); } - UnownedStringSlice prefix = (key.kind == CommandOptions::LookupKind::Category) ? - m_commandOptions->getFirstNameForCategory(index) : - m_commandOptions->getFirstNameForOption(index); + UnownedStringSlice prefix = (key.kind == CommandOptions::LookupKind::Category) + ? m_commandOptions->getFirstNameForCategory(index) + : m_commandOptions->getFirstNameForOption(index); prefix = prefix.trim('-'); if (prefix.getLength() == 0) @@ -406,17 +446,17 @@ UnownedStringSlice MarkdownCommandOptionsWriter::_getLinkName(const NameKey& key return m_pool.getSlice(handle); } -UnownedStringSlice MarkdownCommandOptionsWriter::_getLinkName(CommandOptions::LookupKind kind, Index index) +UnownedStringSlice MarkdownCommandOptionsWriter::_getLinkName( + CommandOptions::LookupKind kind, + Index index) { auto& options = *m_commandOptions; - // Set up the name key - const auto key = (kind == LookupKind::Category) ? - options.getNameKeyForCategory(index) : - options.getNameKeyForOption(index); - - return _getLinkName(key, index); + // Set up the name key + const auto key = (kind == LookupKind::Category) ? options.getNameKeyForCategory(index) + : options.getNameKeyForOption(index); + return _getLinkName(key, index); } /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TextCommandOptionsWriter !!!!!!!!!!!!!!!!!!!!!!!!!!! */ @@ -425,11 +465,12 @@ class TextCommandOptionsWriter : public CommandOptionsWriter { public: typedef CommandOptionsWriter Super; - - TextCommandOptionsWriter(const Options& options) : - Super(options) + + TextCommandOptionsWriter(const Options& options) + : Super(options) { } + protected: // CommandOptionsWriter virtual void appendDescriptionForCategoryImpl(Index categoryIndex) SLANG_OVERRIDE; @@ -580,26 +621,24 @@ void TextCommandOptionsWriter::_appendText(Count indentCount, const UnownedStrin typedef CommandOptionsWriter::Style Style; -static const NamesDescriptionValue s_styleInfos[] = -{ - { ValueInt(Style::Text), "text", "Text suitable for output to a terminal" }, - { ValueInt(Style::Markdown), "markdown", "Markdown" }, - { ValueInt(Style::NoLinkMarkdown), "no-link-markdown", "Markdown without links" }, +static const NamesDescriptionValue s_styleInfos[] = { + {ValueInt(Style::Text), "text", "Text suitable for output to a terminal"}, + {ValueInt(Style::Markdown), "markdown", "Markdown"}, + {ValueInt(Style::NoLinkMarkdown), "no-link-markdown", "Markdown without links"}, }; -/* static */ConstArrayView CommandOptionsWriter::getStyleInfos() +/* static */ ConstArrayView CommandOptionsWriter::getStyleInfos() { return makeConstArrayView(s_styleInfos); } -CommandOptionsWriter::CommandOptionsWriter(const Options& options) : - m_pool(StringSlicePool::Style::Default), - m_options(options) +CommandOptionsWriter::CommandOptionsWriter(const Options& options) + : m_pool(StringSlicePool::Style::Default), m_options(options) { m_options.indent = m_pool.addAndGetSlice(options.indent); } -/* static */RefPtr CommandOptionsWriter::create(const Options& options) +/* static */ RefPtr CommandOptionsWriter::create(const Options& options) { if (_isMarkdown(options.style)) { @@ -611,7 +650,9 @@ CommandOptionsWriter::CommandOptionsWriter(const Options& options) : } } -void CommandOptionsWriter::appendDescriptionForCategory(CommandOptions* options, Index categoryIndex) +void CommandOptionsWriter::appendDescriptionForCategory( + CommandOptions* options, + Index categoryIndex) { m_commandOptions = options; appendDescriptionForCategoryImpl(categoryIndex); @@ -667,7 +708,10 @@ void CommandOptionsWriter::_requireIndent(Count indentCount) } } -void CommandOptionsWriter::_appendWrappedIndented(Count indentCount, List& slices, const UnownedStringSlice& delimit) +void CommandOptionsWriter::_appendWrappedIndented( + Count indentCount, + List& slices, + const UnownedStringSlice& delimit) { Count lineLength = _getCurrentLineLength(); @@ -708,5 +752,3 @@ void CommandOptionsWriter::_appendWrappedIndented(Count indentCount, List getStyleInfos(); struct Options { - Style style = Style::Text; ///< The style - Index lineLength = 120; ///< The maximum amount of characters on a line - UnownedStringSlice indent = toSlice(" ");; + Style style = Style::Text; ///< The style + Index lineLength = 120; ///< The maximum amount of characters on a line + UnownedStringSlice indent = toSlice(" "); + ; }; - /// Append descirption for a category + /// Append descirption for a category void appendDescriptionForCategory(CommandOptions* options, Index categoryIndex); - /// Appends a description of all of the options + /// Appends a description of all of the options void appendDescription(CommandOptions* options); - /// Get the builder that string is being written to + /// Get the builder that string is being written to StringBuilder& getBuilder() { return m_builder; } static RefPtr create(const Options& options); - -protected: - /// Append descirption for a category +protected: + /// Append descirption for a category virtual void appendDescriptionForCategoryImpl(Index categoryIndex) = 0; - /// Appends a description of all of the options + /// Appends a description of all of the options virtual void appendDescriptionImpl() = 0; // Ctor, use create to create a writer CommandOptionsWriter(const Options& options); - /// Get the length of the current line in ascii chars/bytes + /// Get the length of the current line in ascii chars/bytes Count _getCurrentLineLength(); - /// Indentation/wrapping + /// Indentation/wrapping void _requireIndent(Count indentCount); - void _appendWrappedIndented(Count indentCount, List& slices, const UnownedStringSlice& delimit); - + void _appendWrappedIndented( + Count indentCount, + List& slices, + const UnownedStringSlice& delimit); + CommandOptions* m_commandOptions = nullptr; - StringSlicePool m_pool; + StringSlicePool m_pool; StringBuilder m_builder; Options m_options; }; } // namespace Slang -#endif +#endif diff --git a/source/core/slang-command-options.cpp b/source/core/slang-command-options.cpp index 5bbe59a0d..a4bb8b552 100644 --- a/source/core/slang-command-options.cpp +++ b/source/core/slang-command-options.cpp @@ -2,11 +2,12 @@ #include "slang-command-options.h" -#include "slang-string-util.h" -#include "slang-char-util.h" #include "slang-byte-encode-util.h" +#include "slang-char-util.h" +#include "slang-string-util.h" -namespace Slang { +namespace Slang +{ UnownedStringSlice CommandOptions::getFirstNameForOption(Index optionIndex) { @@ -26,7 +27,8 @@ CommandOptions::NameKey CommandOptions::getNameKeyForOption(Index optionIndex) const auto& cat = m_categories[opt.categoryIndex]; NameKey key; key.nameIndex = m_pool.findIndex(getFirstNameForOption(optionIndex)); - key.kind = (cat.kind == CategoryKind::Option) ? LookupKind::Option : makeLookupKind(opt.categoryIndex); + key.kind = + (cat.kind == CategoryKind::Option) ? LookupKind::Option : makeLookupKind(opt.categoryIndex); return key; } @@ -38,7 +40,10 @@ CommandOptions::NameKey CommandOptions::getNameKeyForCategory(Index categoryInde return key; } -SlangResult CommandOptions::_addName(LookupKind kind, const UnownedStringSlice& name, Index targetIndex) +SlangResult CommandOptions::_addName( + LookupKind kind, + const UnownedStringSlice& name, + Index targetIndex) { NameKey nameKey; nameKey.kind = kind; @@ -52,7 +57,10 @@ SlangResult CommandOptions::_addName(LookupKind kind, const UnownedStringSlice& return SLANG_OK; } -SlangResult CommandOptions::_addOptionName(const UnownedStringSlice& name, Flags flags, Index targetIndex) +SlangResult CommandOptions::_addOptionName( + const UnownedStringSlice& name, + Flags flags, + Index targetIndex) { SLANG_RETURN_ON_FAIL(_addName(LookupKind::Option, name, targetIndex)); @@ -67,7 +75,10 @@ SlangResult CommandOptions::_addOptionName(const UnownedStringSlice& name, Flags return SLANG_OK; } -SlangResult CommandOptions::_addValueName(const UnownedStringSlice& name, Index categoryIndex, Index optionIndex) +SlangResult CommandOptions::_addValueName( + const UnownedStringSlice& name, + Index categoryIndex, + Index optionIndex) { return _addName(LookupKind(categoryIndex), name, optionIndex); } @@ -122,7 +133,10 @@ Index CommandOptions::_addOption(const UnownedStringSlice& name, const Option& i } } -Index CommandOptions::_addOption(const UnownedStringSlice* names, Count namesCount, const Option& inOption) +Index CommandOptions::_addOption( + const UnownedStringSlice* names, + Count namesCount, + const Option& inOption) { SLANG_ASSERT(namesCount > 0); SLANG_ASSERT(inOption.categoryIndex >= 0); @@ -134,7 +148,8 @@ Index CommandOptions::_addOption(const UnownedStringSlice* names, Count namesCou auto& cat = m_categories[inOption.categoryIndex]; - // If there are already options associated with this category, we have to be in the run of the last ones added + // If there are already options associated with this category, we have to be in the run of the + // last ones added if (cat.optionStartIndex != cat.optionEndIndex) { // If we aren't at the end then this is an error @@ -172,9 +187,10 @@ Index CommandOptions::_addOption(const UnownedStringSlice* names, Count namesCou { for (Index i = 0; i < namesCount; ++i) { - _addValueName(names[i], inOption.categoryIndex, optionIndex); + _addValueName(names[i], inOption.categoryIndex, optionIndex); } - if (SLANG_FAILED(_addUserValue(LookupKind(inOption.categoryIndex), inOption.userValue, optionIndex))) + if (SLANG_FAILED( + _addUserValue(LookupKind(inOption.categoryIndex), inOption.userValue, optionIndex))) { return -1; } @@ -198,7 +214,7 @@ Index CommandOptions::_addOption(const UnownedStringSlice* names, Count namesCou // Set the end index cat.optionEndIndex = optionIndex + 1; - + return optionIndex; } @@ -219,7 +235,11 @@ static void _handlePostFix(UnownedStringSlice& ioSlice, CommandOptions::Flags& i } } -void CommandOptions::add(const char* inName, const char* usage, const char* description, UserValue userValue) +void CommandOptions::add( + const char* inName, + const char* usage, + const char* description, + UserValue userValue) { UnownedStringSlice nameSlice(inName); @@ -250,7 +270,13 @@ void CommandOptions::add(const char* inName, const char* usage, const char* desc } } -void CommandOptions::add(const UnownedStringSlice* names, Count namesCount, const char* usage, const char* description, UserValue userValue, Flags flags) +void CommandOptions::add( + const UnownedStringSlice* names, + Count namesCount, + const char* usage, + const char* description, + UserValue userValue, + Flags flags) { Option option; option.categoryIndex = m_currentCategoryIndex; @@ -337,7 +363,10 @@ void CommandOptions::addValue(const UnownedStringSlice& name, UserValue userValu _addValue(name, option); } -void CommandOptions::addValue(const UnownedStringSlice& name, const UnownedStringSlice& description, UserValue userValue) +void CommandOptions::addValue( + const UnownedStringSlice& name, + const UnownedStringSlice& description, + UserValue userValue) { Option option; option.categoryIndex = m_currentCategoryIndex; @@ -346,7 +375,10 @@ void CommandOptions::addValue(const UnownedStringSlice& name, const UnownedStrin _addValue(name, option); } -void CommandOptions::addValue(const UnownedStringSlice* names, Count namesCount, UserValue userValue) +void CommandOptions::addValue( + const UnownedStringSlice* names, + Count namesCount, + UserValue userValue) { Option option; option.categoryIndex = m_currentCategoryIndex; @@ -377,7 +409,11 @@ void CommandOptions::addValue(const char* name, UserValue userValue) addValue(UnownedStringSlice(name), userValue); } -Index CommandOptions::addCategory(CategoryKind kind, const char* name, const char* description, UserValue userValue) +Index CommandOptions::addCategory( + CategoryKind kind, + const char* name, + const char* description, + UserValue userValue) { const UnownedStringSlice nameSlice(name); @@ -425,7 +461,10 @@ void CommandOptions::setCategory(const char* name) m_currentCategoryIndex = -1; } -Index CommandOptions::findTargetIndexByName(LookupKind kind, const UnownedStringSlice& name, NameKey* outNameKey) const +Index CommandOptions::findTargetIndexByName( + LookupKind kind, + const UnownedStringSlice& name, + NameKey* outNameKey) const { // Look up directly { @@ -470,7 +509,10 @@ Index CommandOptions::findTargetIndexByName(LookupKind kind, const UnownedString return -1; } -Index CommandOptions::_findTargetIndexByName(LookupKind kind, const UnownedStringSlice& name, NameKey* outNameKey) const +Index CommandOptions::_findTargetIndexByName( + LookupKind kind, + const UnownedStringSlice& name, + NameKey* outNameKey) const { const auto nameIndex = m_pool.findIndex(name); // If the name isn't in the pool then there isn't a category with this name @@ -524,7 +566,9 @@ Index CommandOptions::findCategoryByCaseInsensitiveName(const UnownedStringSlice return -1; } -Index CommandOptions::findOptionByCategoryUserValue(UserValue categoryUserValue, const UnownedStringSlice& name) const +Index CommandOptions::findOptionByCategoryUserValue( + UserValue categoryUserValue, + const UnownedStringSlice& name) const { Index categoryIndex = findTargetIndexByUserValue(LookupKind::Category, categoryUserValue); if (categoryIndex < 0) @@ -535,14 +579,19 @@ Index CommandOptions::findOptionByCategoryUserValue(UserValue categoryUserValue, return findValueByName(categoryIndex, name); } -ConstArrayView CommandOptions::getOptionsForCategory(Index categoryIndex) const +ConstArrayView CommandOptions::getOptionsForCategory( + Index categoryIndex) const { const auto& cat = m_categories[categoryIndex]; - return makeConstArrayView(m_options.getBuffer() + cat.optionStartIndex, cat.optionEndIndex - cat.optionStartIndex); + return makeConstArrayView( + m_options.getBuffer() + cat.optionStartIndex, + cat.optionEndIndex - cat.optionStartIndex); } -void CommandOptions::appendCategoryOptionNames(Index categoryIndex, List& outNames) const +void CommandOptions::appendCategoryOptionNames( + Index categoryIndex, + List& outNames) const { for (const auto& option : getOptionsForCategory(categoryIndex)) { @@ -550,28 +599,33 @@ void CommandOptions::appendCategoryOptionNames(Index categoryIndex, List& outNames) const +void CommandOptions::getCategoryOptionNames(Index categoryIndex, List& outNames) + const { outNames.clear(); appendCategoryOptionNames(categoryIndex, outNames); } -void CommandOptions::splitUsage(const UnownedStringSlice& usageSlice, List& outSlices) const +void CommandOptions::splitUsage( + const UnownedStringSlice& usageSlice, + List& outSlices) const { const auto* cur = usageSlice.begin(); const auto* end = usageSlice.end(); while (cur < end) { - // Find < - while (cur < end && *cur != '<') cur++; + // Find < + while (cur < end && *cur != '<') + cur++; // If we found it look for the end if (cur < end && *cur == '<') { ++cur; auto start = cur; - while (cur < end && (CharUtil::isAlphaOrDigit(*cur) || *cur == '-' || *cur == '_') && *cur != '>') + while (cur < end && (CharUtil::isAlphaOrDigit(*cur) || *cur == '-' || *cur == '_') && + *cur != '>') { cur++; } @@ -594,7 +648,9 @@ void CommandOptions::splitUsage(const UnownedStringSlice& usageSlice, List& outCategories) const +void CommandOptions::findCategoryIndicesFromUsage( + const UnownedStringSlice& slice, + List& outCategories) const { List categoryNames; splitUsage(slice, categoryNames); @@ -609,7 +665,10 @@ void CommandOptions::findCategoryIndicesFromUsage(const UnownedStringSlice& slic } } -Count CommandOptions::getOptionCountInRange(Index categoryIndex, UserValue start, UserValue nonInclEnd) const +Count CommandOptions::getOptionCountInRange( + Index categoryIndex, + UserValue start, + UserValue nonInclEnd) const { const UserIndex startIndex = UserIndex(start); const UserIndex endIndex = UserIndex(nonInclEnd); @@ -631,7 +690,8 @@ Count CommandOptions::getOptionCountInRange(Index categoryIndex, UserValue start return count; } -Count CommandOptions::getOptionCountInRange(LookupKind kind, UserValue start, UserValue nonInclEnd) const +Count CommandOptions::getOptionCountInRange(LookupKind kind, UserValue start, UserValue nonInclEnd) + const { Index count = 0; @@ -671,7 +731,10 @@ Count CommandOptions::getOptionCountInRange(LookupKind kind, UserValue start, Us } -bool CommandOptions::hasContiguousUserValueRange(LookupKind kind, UserValue start, UserValue nonInclEnd) const +bool CommandOptions::hasContiguousUserValueRange( + LookupKind kind, + UserValue start, + UserValue nonInclEnd) const { const Count rangeCount = Count(nonInclEnd) - Count(start); SLANG_ASSERT(rangeCount >= 0); @@ -686,5 +749,3 @@ bool CommandOptions::hasContiguousUserValueRange(LookupKind kind, UserValue star } } // namespace Slang - - diff --git a/source/core/slang-command-options.h b/source/core/slang-command-options.h index 8b6d7b0ce..9d7af44d9 100644 --- a/source/core/slang-command-options.h +++ b/source/core/slang-command-options.h @@ -2,13 +2,13 @@ #define SLANG_CORE_COMMAND_OPTIONS_H #include "slang-basic.h" -#include "slang-string-slice-pool.h" #include "slang-name-value.h" +#include "slang-string-slice-pool.h" namespace Slang { -/* For convenience we encode within "names" flags. +/* For convenience we encode within "names" flags. "-D..." means that -D *must* be followed by the value "-D?..." means that -D *can* be a prefix, or it might be followed with the arg */ @@ -23,29 +23,36 @@ struct CommandOptions enum class LookupKind : int32_t { - Category = -2, ///< Lookup a category name - Option = -1, ///< Lookup an option name (all options use the same lookup index even if in different categories) - Base = 0, ///< Lookup via category index + Category = -2, ///< Lookup a category name + Option = -1, ///< Lookup an option name (all options use the same lookup index even if in + ///< different categories) + Base = 0, ///< Lookup via category index }; - /// A key type that uses the combination of the lookup kind and a name index. - /// Maps to a target index that could be a category or an option index. + /// A key type that uses the combination of the lookup kind and a name index. + /// Maps to a target index that could be a category or an option index. struct NameKey { typedef NameKey ThisType; - SLANG_FORCE_INLINE bool operator==(const ThisType& rhs) const { return kind == rhs.kind && nameIndex == rhs.nameIndex; } + SLANG_FORCE_INLINE bool operator==(const ThisType& rhs) const + { + return kind == rhs.kind && nameIndex == rhs.nameIndex; + } SLANG_FORCE_INLINE bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } - HashCode getHashCode() const { return combineHash(Slang::getHashCode(kind), Slang::getHashCode(nameIndex)); } + HashCode getHashCode() const + { + return combineHash(Slang::getHashCode(kind), Slang::getHashCode(nameIndex)); + } - LookupKind kind; ///< The kind of lookup - Index nameIndex; ///< The name index in the pool + LookupKind kind; ///< The kind of lookup + Index nameIndex; ///< The name index in the pool }; enum class CategoryKind { - Option, ///< Command line option (like "-D") - Value, ///< One of a set of values (such as an enum or some other kind of list of values) + Option, ///< Command line option (like "-D") + Value, ///< One of a set of values (such as an enum or some other kind of list of values) }; struct ValuePair @@ -71,128 +78,179 @@ struct CommandOptions { enum Enum : Flags { - CanPrefix = 0x1, /// Allows -Dfsggf or -D fdsfsd - IsPrefix = 0x2, /// Is an option that can only be a prefix + CanPrefix = 0x1, /// Allows -Dfsggf or -D fdsfsd + IsPrefix = 0x2, /// Is an option that can only be a prefix }; }; struct Option { - UnownedStringSlice names; ///< Comma delimited list of names, first name is the default - UnownedStringSlice usage; ///< Describes usage, can be empty - UnownedStringSlice description; ///< A description of usage + UnownedStringSlice names; ///< Comma delimited list of names, first name is the default + UnownedStringSlice usage; ///< Describes usage, can be empty + UnownedStringSlice description; ///< A description of usage UserValue userValue = kInvalidUserValue; - Index categoryIndex = -1; ///< Category this option belongs to - Flags flags = 0; ///< Flags about this option + Index categoryIndex = -1; ///< Category this option belongs to + Flags flags = 0; ///< Flags about this option }; - /// Get the first name + /// Get the first name UnownedStringSlice getFirstNameForOption(Index optionIndex); - /// Get the first name for the category + /// Get the first name for the category UnownedStringSlice getFirstNameForCategory(Index categoryIndex); - /// Get a name key for an opton + /// Get a name key for an opton NameKey getNameKeyForOption(Index optionIndex); - /// Get a name key for a category + /// Get a name key for a category NameKey getNameKeyForCategory(Index optionIndex); - /// Add a category - Index addCategory(CategoryKind kind, const char* name, const char* description, UserValue userValue = kInvalidUserValue); - /// Use an already known category. It's an error if the category isn't found + /// Add a category + Index addCategory( + CategoryKind kind, + const char* name, + const char* description, + UserValue userValue = kInvalidUserValue); + /// Use an already known category. It's an error if the category isn't found void setCategory(const char* name); - void add(const char* name, const char* usage, const char* description, UserValue userValue = kInvalidUserValue); - void add(const UnownedStringSlice* names, Count namesCount, const char* usage, const char* description, UserValue userValue = kInvalidUserValue, Flags flags = 0); + void add( + const char* name, + const char* usage, + const char* description, + UserValue userValue = kInvalidUserValue); + void add( + const UnownedStringSlice* names, + Count namesCount, + const char* usage, + const char* description, + UserValue userValue = kInvalidUserValue, + Flags flags = 0); void addValue(const UnownedStringSlice& name, UserValue userValue = kInvalidUserValue); - void addValue(const UnownedStringSlice& name, const UnownedStringSlice& description, UserValue userValue = kInvalidUserValue); - void addValue(const char* name, const char* description, UserValue userValue = kInvalidUserValue); + void addValue( + const UnownedStringSlice& name, + const UnownedStringSlice& description, + UserValue userValue = kInvalidUserValue); + void addValue( + const char* name, + const char* description, + UserValue userValue = kInvalidUserValue); void addValue(const char* name, UserValue userValue = kInvalidUserValue); - void addValue(const UnownedStringSlice* names, Count namesCount, UserValue userValue = kInvalidUserValue); + void addValue( + const UnownedStringSlice* names, + Count namesCount, + UserValue userValue = kInvalidUserValue); - /// Add values (without UserValue association) + /// Add values (without UserValue association) void addValues(const ValuePair* pairs, Count pairsCount); - /// Add values + /// Add values void addValues(const ConstArrayView& values); void addValues(const ConstArrayView& values); void addValues(const ConstArrayView& values); - /// Sometimes values are listed with *names* per value. This method will take into account the aliases + /// Sometimes values are listed with *names* per value. This method will take into account the + /// aliases void addValuesWithAliases(const ConstArrayView& values); - /// Get the target index based off the name and the kind - Index findTargetIndexByName(LookupKind kind, const UnownedStringSlice& name, NameKey* outNameKey = nullptr) const; - /// Given a kind and a user value lookup the target index + /// Get the target index based off the name and the kind + Index findTargetIndexByName( + LookupKind kind, + const UnownedStringSlice& name, + NameKey* outNameKey = nullptr) const; + /// Given a kind and a user value lookup the target index Index findTargetIndexByUserValue(LookupKind kind, UserValue userValue) const; - /// Finds the category by name or -1 if not found - Index findCategoryByName(const UnownedStringSlice& name) const { return findTargetIndexByName(LookupKind::Category, name); } - /// Finds the option index by name or -1 if not found - Index findOptionByName(const UnownedStringSlice& name) const { return findTargetIndexByName(LookupKind::Option, name); } - /// Find the option index of a value, using it's category index and the name - Index findValueByName(Index categoryIndex, const UnownedStringSlice& name) const { return findTargetIndexByName(LookupKind(categoryIndex), name); } - - /// Get the category index from a user value - Index findCategoryByUserValue(UserValue userValue) const { return findTargetIndexByUserValue(LookupKind::Category, userValue); } - /// Can only get options - Index findOptionByUserValue(UserValue userValue) const { return findTargetIndexByUserValue(LookupKind::Option, userValue); } - /// Get a value associated with a category - Index findValueByUserValue(Index categoryIndex, UserValue userValue) const { return findTargetIndexByUserValue(LookupKind(categoryIndex), userValue); } - - /// Given a category user value, find the associated name - /// Returns -1 if not found - Index findOptionByCategoryUserValue(UserValue categoryUserValue, const UnownedStringSlice& name) const; - - /// Find a category by case insensitive name. Returns -1 if not found + /// Finds the category by name or -1 if not found + Index findCategoryByName(const UnownedStringSlice& name) const + { + return findTargetIndexByName(LookupKind::Category, name); + } + /// Finds the option index by name or -1 if not found + Index findOptionByName(const UnownedStringSlice& name) const + { + return findTargetIndexByName(LookupKind::Option, name); + } + /// Find the option index of a value, using it's category index and the name + Index findValueByName(Index categoryIndex, const UnownedStringSlice& name) const + { + return findTargetIndexByName(LookupKind(categoryIndex), name); + } + + /// Get the category index from a user value + Index findCategoryByUserValue(UserValue userValue) const + { + return findTargetIndexByUserValue(LookupKind::Category, userValue); + } + /// Can only get options + Index findOptionByUserValue(UserValue userValue) const + { + return findTargetIndexByUserValue(LookupKind::Option, userValue); + } + /// Get a value associated with a category + Index findValueByUserValue(Index categoryIndex, UserValue userValue) const + { + return findTargetIndexByUserValue(LookupKind(categoryIndex), userValue); + } + + /// Given a category user value, find the associated name + /// Returns -1 if not found + Index findOptionByCategoryUserValue(UserValue categoryUserValue, const UnownedStringSlice& name) + const; + + /// Find a category by case insensitive name. Returns -1 if not found Index findCategoryByCaseInsensitiveName(const UnownedStringSlice& slice) const; - - /// Given a category index returns all the options associated. + + /// Given a category index returns all the options associated. ConstArrayView